<commit_before>#ifndef CONST_HPP_
#define CONST_HPP_

#include <iostream>
#include <string>

// All about "const" key word

// From Item 2 of book "Effective C++" by Scott Meyers:
// Prefer const values to #defines

// We could use #define to create constant value
#define TEN 10
// Advantages:
// - we could create constant value
// - defines are compatible with C code

// Disadvantages
// - defines are just symbolic names. Compiler substitute define with its value
// in code. Compiler could remove name of the define from symbolic table and
// make your debug session harder. Also because of substitutions your code
// tend to increase in size - in every place where you have difene you will get
// new variable.
// - defines are public. If you put define in header and include that header
// in some other source file, you will be able to access your define in that
// source file. You could constrain visibility of define if you put it into
// .cpp file - it will be visible only in that cpp file.

// Global const value
const int RATE = 110;
const char* const AUTHOR_NAME = "Antony Cherepanov";
// it is better to use std::string instead of char*
const std::string ONE("one");

// How to make class-specific const value
class Container
{
public:
    // Member "value" will be created in each object of the Container class
    const int value = 1;
    // Member "rate" will be created only once and will be used by all objects
    // of the Container class
    static const int rate = 100;
};

// The enum hack
// "The enum hack is worth knowing about for several reasons. First, the
// enum hack behaves in some ways more like a #define than a const
// does, and sometimes that’s what you want. For example, it’s legal to
// take the address of a const, but it’s not legal to take the address of an
// enum, and it’s typically not legal to take the address of a #define,
// either.
//
// A second reason to know about the enum hack is purely pragmatic.
// Lots of code employs it, so you need to recognize it when you see it. In
// fact, the enum hack is a fundamental technique of template metaprogramming."
class Hacked
{
public:
    enum {SIZE = 16};
    int array[SIZE];
};

void ConstExamples();
void ConstReferences();
void ConstPointers();

#endif /* CONST_HPP_ */
<commit_msg>Add comment to const.hpp<commit_after>#ifndef CONST_HPP_
#define CONST_HPP_

#include <iostream>
#include <string>

// All about "const" key word

// From Item 2 of book "Effective C++" by Scott Meyers:
// Prefer const values to #defines

// We could use #define to create constant value
#define TEN 10
// Advantages:
// - we could create constant value
// - defines are compatible with C code

// Disadvantages
// - defines are just symbolic names. Compiler substitute define with its value
// in code. Compiler could remove name of the define from symbolic table and
// make your debug session harder. Also because of substitutions your code
// tend to increase in size - in every place where you have difene you will get
// new variable.
// - defines are public. If you put define in header and include that header
// in some other source file, you will be able to access your define in that
// source file. You could constrain visibility of define if you put it into
// .cpp file - it will be visible only in that cpp file.

// Global const value
const int RATE = 110;
const char* const AUTHOR_NAME = "Antony Cherepanov";
// it is better to use std::string instead of char*
const std::string ONE("one");

// How to make class-specific const value
class Container
{
public:
    // Member "value" will be created in each object of the Container class
    const int value = 1;
    // Member "rate" will be created only once and will be used by all objects
    // of the Container class
    static const int rate = 100;
};

// The enum hack
// "The enum hack is worth knowing about for several reasons. First, the
// enum hack behaves in some ways more like a #define than a const
// does, and sometimes that’s what you want. For example, it’s legal to
// take the address of a const, but it’s not legal to take the address of an
// enum, and it’s typically not legal to take the address of a #define,
// either.
//
// A second reason to know about the enum hack is purely pragmatic.
// Lots of code employs it, so you need to recognize it when you see it. In
// fact, the enum hack is a fundamental technique of template metaprogramming."
//
// Assume that you need the value of a class constant during compilation of
// the class, such as in the declaration of the array
class Hacked
{
public:
    enum {SIZE = 16};
    int array[SIZE];
};

void ConstExamples();
void ConstReferences();
void ConstPointers();

#endif /* CONST_HPP_ */
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    FEMImageRegLMEx.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) 2002 Insight Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for detail.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

// disable debug warnings in MS compiler
#ifdef _MSC_VER
#pragma warning(disable: 4786)
#endif
#include <fstream>

#include "FEMImageRegLMEx.h"

// Below, we have typedefs that instantiate all necessary classes.
// Here, we instantiate the image type, load type and
// explicitly template the load implementation type.

#define TWOD
//#define THREED
#ifdef TWOD
typedef itk::Image< unsigned char, 2 >                     fileImageType;
typedef itk::Image< float, 2 >                     ImageType;
// We now declare an element type and load implementation pointer for the visitor class.
typedef itk::fem::Element2DC0LinearTriangularMembrane   ElementType2;
typedef itk::fem::Element2DC0LinearQuadrilateralMembrane   ElementType;
#endif
#ifdef THREED
typedef itk::Image< unsigned char, 3 >                     fileImageType;
typedef itk::Image< float, 3 >                     ImageType;
typedef itk::fem::Element3DC0LinearHexahedronMembrane   ElementType;
typedef itk::fem::Element3DC0LinearTetrahedronMembrane   ElementType2;
#endif
typedef itk::fem::ImageMetricLoad<ImageType,ImageType>     ImageLoadType;
template class itk::fem::ImageMetricLoadImplementation<ImageLoadType>;
typedef ElementType::LoadImplementationFunctionPointer     LoadImpFP;
typedef ElementType::LoadType                              ElementLoadType;
typedef ElementType2::LoadImplementationFunctionPointer     LoadImpFP2;
typedef ElementType2::LoadType                              ElementLoadType2;
typedef itk::fem::VisitorDispatcher<ElementType,ElementLoadType, LoadImpFP>
                                                          DispatcherType;
typedef itk::fem::VisitorDispatcher<ElementType2,ElementLoadType2, LoadImpFP2>
                                                          DispatcherType2;

typedef itk::fem::FEMRegistrationFilter<ImageType,ImageType> RegistrationType;

void ReadRawImageFiles( RegistrationType* X)
{

  typedef  itk::ImageFileReader< fileImageType >      FileSourceType;
  typedef  fileImageType::PixelType PixType;
  const unsigned int ImageDimension=fileImageType::ImageDimension;
  typedef  itk::RawImageIO< PixType,ImageDimension>   RawReaderType;

  FileSourceType::Pointer reffilter = FileSourceType::New();
  reffilter->SetFileName( X->GetReferenceFile() );
  FileSourceType::Pointer tarfilter = FileSourceType::New();
  tarfilter->SetFileName( X->GetTargetFile() );

  RawReaderType::Pointer  rawReader  = RawReaderType::New();
  rawReader->SetFileDimensionality( ImageDimension );

  ImageType::SizeType ImageSize=X->GetImageSize();
  for (unsigned int ii=0; ii<ImageDimension; ii++)
  {
    unsigned int temp=(unsigned int) ImageSize[ii];
    rawReader->SetDimensions( ii, temp );
  }
  reffilter->SetImageIO( rawReader );
  tarfilter->SetImageIO( rawReader );

  try
    {
    reffilter->Update();
    }
  catch( itk::ExceptionObject & e )
    {
    std::cerr << "Exception caught during reference file reading " << std::endl;
    std::cerr << e << std::endl;
    return ;
    }
  try
    {
    tarfilter->Update();
    }
  catch( itk::ExceptionObject & e )
    {
    std::cerr << "Exception caught during target file reading " << std::endl;
    std::cerr << e << std::endl;
    return ;
    }

  typedef itk::RescaleIntensityImageFilter<fileImageType,ImageType> FilterType;
  FilterType::Pointer refrescalefilter = FilterType::New();
  FilterType::Pointer tarrescalefilter = FilterType::New();

  refrescalefilter->SetInput(reffilter->GetOutput());
  tarrescalefilter->SetInput(tarfilter->GetOutput());

  const double desiredMinimum =  0.0;
  const double desiredMaximum =  255.0;

  refrescalefilter->SetOutputMinimum( desiredMinimum );
  refrescalefilter->SetOutputMaximum( desiredMaximum );
  refrescalefilter->UpdateLargestPossibleRegion();
  tarrescalefilter->SetOutputMinimum( desiredMinimum );
  tarrescalefilter->SetOutputMaximum( desiredMaximum );
  tarrescalefilter->UpdateLargestPossibleRegion();

  typedef itk::HistogramMatchingImageFilter<ImageType,ImageType> HEFilterType;
  HEFilterType::Pointer IntensityEqualizeFilter = HEFilterType::New();

  IntensityEqualizeFilter->SetReferenceImage( refrescalefilter->GetOutput() );
  IntensityEqualizeFilter->SetInput( tarrescalefilter->GetOutput() );
  IntensityEqualizeFilter->SetNumberOfHistogramLevels( 100);
  IntensityEqualizeFilter->SetNumberOfMatchPoints( 15);
  IntensityEqualizeFilter->ThresholdAtMeanIntensityOn();
  IntensityEqualizeFilter->Update();

  X->SetReferenceImage(refrescalefilter->GetOutput());
  X->SetTargetImage(IntensityEqualizeFilter->GetOutput()/*tarrescalefilter->GetOutput()*/);
//  X->SetReferenceImage(reffilter->GetOutput());
//  X->SetTargetImage(tarfilter->GetOutput());
}

int main()
{

// Register the correct load implementation with the element typed visitor dispatcher.
  {
    ElementType::LoadImplementationFunctionPointer fp = itk::fem::ImageMetricLoadImplementation<ImageLoadType>::ImplementImageMetricLoad;
    DispatcherType::RegisterVisitor((ImageLoadType*)0,fp);
  }
  {
    ElementType2::LoadImplementationFunctionPointer fp = itk::fem::ImageMetricLoadImplementation<ImageLoadType>::ImplementImageMetricLoad;
    DispatcherType2::RegisterVisitor((ImageLoadType*)0,fp);
  }

  RegistrationType::Pointer X= RegistrationType::New(); // Declare the registration class

  X->SetConfigFileName("U://itk//Insight//Examples//FEM//FEMregLMparams.txt");
  //X->SetConfigFileName("c:\\itk\\Insight\\Examples\\FEM\\FEMregLMparams.txt");
  if (!X->ReadConfigFile(X->GetConfigFileName())) { return -1; }

  // Read Raw Files
  ReadRawImageFiles(X);

  // Choose the material properties
  itk::fem::MaterialLinearElasticity::Pointer m;
  m=itk::fem::MaterialLinearElasticity::New();
  m->GN=0;       // Global number of the material ///
  m->E=X->GetElasticity();  // Young modulus -- used in the membrane ///
  m->A=1.0;     // Crossection area ///
  m->h=1.0;     // Crossection area ///
  m->I=1.0;    // Moment of inertia ///
  m->nu=0.; //.0;    // poissons -- DONT CHOOSE 1.0!!///
  m->RhoC=1.0;

  // Create the element type
  ElementType::Pointer e1=ElementType::New();
  e1->m_mat=dynamic_cast<itk::fem::MaterialLinearElasticity*>( m );
  X->SetElement(e1);
  X->SetMaterial(m);

  // Register the images
  X->RunRegistration();

  // Get outputs -- in image or vector field form
  X->WriteWarpedImage(X->GetResultsFileName());

  X->SetWriteDisplacements(false);
  if (X->GetWriteDisplacements()) {
    X->WriteDisplacementField(0);
    X->WriteDisplacementField(1);
  }
  delete e1;
  delete m;
  return 0;
}

<commit_msg>FIX: Errors on some compilers non-implicit of a function).<commit_after>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    FEMImageRegLMEx.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) 2002 Insight Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for detail.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

// disable debug warnings in MS compiler
#ifdef _MSC_VER
#pragma warning(disable: 4786)
#endif
#include <fstream>

#include "FEMImageRegLMEx.h"

// Below, we have typedefs that instantiate all necessary classes.
// Here, we instantiate the image type, load type and
// explicitly template the load implementation type.

#define TWOD
//#define THREED
#ifdef TWOD
typedef itk::Image< unsigned char, 2 >                     fileImageType;
typedef itk::Image< float, 2 >                     ImageType;
// We now declare an element type and load implementation pointer for the visitor class.
typedef itk::fem::Element2DC0LinearTriangularMembrane   ElementType2;
typedef itk::fem::Element2DC0LinearQuadrilateralMembrane   ElementType;
#endif
#ifdef THREED
typedef itk::Image< unsigned char, 3 >                     fileImageType;
typedef itk::Image< float, 3 >                     ImageType;
typedef itk::fem::Element3DC0LinearHexahedronMembrane   ElementType;
typedef itk::fem::Element3DC0LinearTetrahedronMembrane   ElementType2;
#endif
typedef itk::fem::ImageMetricLoad<ImageType,ImageType>     ImageLoadType;
template class itk::fem::ImageMetricLoadImplementation<ImageLoadType>;
typedef ElementType::LoadImplementationFunctionPointer     LoadImpFP;
typedef ElementType::LoadType                              ElementLoadType;
typedef ElementType2::LoadImplementationFunctionPointer     LoadImpFP2;
typedef ElementType2::LoadType                              ElementLoadType2;
typedef itk::fem::VisitorDispatcher<ElementType,ElementLoadType, LoadImpFP>
                                                          DispatcherType;
typedef itk::fem::VisitorDispatcher<ElementType2,ElementLoadType2, LoadImpFP2>
                                                          DispatcherType2;

typedef itk::fem::FEMRegistrationFilter<ImageType,ImageType> RegistrationType;

void ReadRawImageFiles( RegistrationType* X)
{

  typedef  itk::ImageFileReader< fileImageType >      FileSourceType;
  typedef  fileImageType::PixelType PixType;
  const unsigned int ImageDimension=fileImageType::ImageDimension;
  typedef  itk::RawImageIO< PixType,ImageDimension>   RawReaderType;

  FileSourceType::Pointer reffilter = FileSourceType::New();
  reffilter->SetFileName( X->GetReferenceFile() );
  FileSourceType::Pointer tarfilter = FileSourceType::New();
  tarfilter->SetFileName( X->GetTargetFile() );

  RawReaderType::Pointer  rawReader  = RawReaderType::New();
  rawReader->SetFileDimensionality( ImageDimension );

  ImageType::SizeType ImageSize=X->GetImageSize();
  for (unsigned int ii=0; ii<ImageDimension; ii++)
  {
    unsigned int temp=(unsigned int) ImageSize[ii];
    rawReader->SetDimensions( ii, temp );
  }
  reffilter->SetImageIO( rawReader );
  tarfilter->SetImageIO( rawReader );

  try
    {
    reffilter->Update();
    }
  catch( itk::ExceptionObject & e )
    {
    std::cerr << "Exception caught during reference file reading " << std::endl;
    std::cerr << e << std::endl;
    return ;
    }
  try
    {
    tarfilter->Update();
    }
  catch( itk::ExceptionObject & e )
    {
    std::cerr << "Exception caught during target file reading " << std::endl;
    std::cerr << e << std::endl;
    return ;
    }

  typedef itk::RescaleIntensityImageFilter<fileImageType,ImageType> FilterType;
  FilterType::Pointer refrescalefilter = FilterType::New();
  FilterType::Pointer tarrescalefilter = FilterType::New();

  refrescalefilter->SetInput(reffilter->GetOutput());
  tarrescalefilter->SetInput(tarfilter->GetOutput());

  const double desiredMinimum =  0.0;
  const double desiredMaximum =  255.0;

  refrescalefilter->SetOutputMinimum( desiredMinimum );
  refrescalefilter->SetOutputMaximum( desiredMaximum );
  refrescalefilter->UpdateLargestPossibleRegion();
  tarrescalefilter->SetOutputMinimum( desiredMinimum );
  tarrescalefilter->SetOutputMaximum( desiredMaximum );
  tarrescalefilter->UpdateLargestPossibleRegion();

  typedef itk::HistogramMatchingImageFilter<ImageType,ImageType> HEFilterType;
  HEFilterType::Pointer IntensityEqualizeFilter = HEFilterType::New();

  IntensityEqualizeFilter->SetReferenceImage( refrescalefilter->GetOutput() );
  IntensityEqualizeFilter->SetInput( tarrescalefilter->GetOutput() );
  IntensityEqualizeFilter->SetNumberOfHistogramLevels( 100);
  IntensityEqualizeFilter->SetNumberOfMatchPoints( 15);
  IntensityEqualizeFilter->ThresholdAtMeanIntensityOn();
  IntensityEqualizeFilter->Update();

  X->SetReferenceImage(refrescalefilter->GetOutput());
  X->SetTargetImage(IntensityEqualizeFilter->GetOutput()/*tarrescalefilter->GetOutput()*/);
//  X->SetReferenceImage(reffilter->GetOutput());
//  X->SetTargetImage(tarfilter->GetOutput());
}

int main()
{

// Register the correct load implementation with the element typed visitor dispatcher.
  {
    ElementType::LoadImplementationFunctionPointer fp = &itk::fem::ImageMetricLoadImplementation<ImageLoadType>::ImplementImageMetricLoad;
    DispatcherType::RegisterVisitor((ImageLoadType*)0,fp);
  }
  {
    ElementType2::LoadImplementationFunctionPointer fp = &itk::fem::ImageMetricLoadImplementation<ImageLoadType>::ImplementImageMetricLoad;
    DispatcherType2::RegisterVisitor((ImageLoadType*)0,fp);
  }

  RegistrationType::Pointer X= RegistrationType::New(); // Declare the registration class

  X->SetConfigFileName("U://itk//Insight//Examples//FEM//FEMregLMparams.txt");
  //X->SetConfigFileName("c:\\itk\\Insight\\Examples\\FEM\\FEMregLMparams.txt");
  if (!X->ReadConfigFile(X->GetConfigFileName())) { return -1; }

  // Read Raw Files
  ReadRawImageFiles(X);

  // Choose the material properties
  itk::fem::MaterialLinearElasticity::Pointer m;
  m=itk::fem::MaterialLinearElasticity::New();
  m->GN=0;       // Global number of the material ///
  m->E=X->GetElasticity();  // Young modulus -- used in the membrane ///
  m->A=1.0;     // Crossection area ///
  m->h=1.0;     // Crossection area ///
  m->I=1.0;    // Moment of inertia ///
  m->nu=0.; //.0;    // poissons -- DONT CHOOSE 1.0!!///
  m->RhoC=1.0;

  // Create the element type
  ElementType::Pointer e1=ElementType::New();
  e1->m_mat=dynamic_cast<itk::fem::MaterialLinearElasticity*>( m );
  X->SetElement(e1);
  X->SetMaterial(m);

  // Register the images
  X->RunRegistration();

  // Get outputs -- in image or vector field form
  X->WriteWarpedImage(X->GetResultsFileName());

  X->SetWriteDisplacements(false);
  if (X->GetWriteDisplacements()) {
    X->WriteDisplacementField(0);
    X->WriteDisplacementField(1);
  }
  delete e1;
  delete m;
  return 0;
}

<|endoftext|>


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

/**
 * @file trajectory_stitcher.cc
 **/

#include "modules/planning/trajectory_stitcher/trajectory_stitcher.h"

#include <algorithm>

#include "modules/common/log.h"
#include "modules/planning/common/planning_gflags.h"
#include "modules/planning/math/double.h"

namespace apollo {
namespace planning {

using apollo::common::TrajectoryPoint;
using apollo::common::VehicleState;

namespace {

std::vector<TrajectoryPoint> ComputeReinitStitchingTrajectory() {
  TrajectoryPoint init_point;
  const auto& vehicle_state = *VehicleState::instance();
  init_point.mutable_path_point()->set_x(vehicle_state.x());
  init_point.mutable_path_point()->set_y(vehicle_state.y());
  init_point.mutable_path_point()->set_z(vehicle_state.z());
  init_point.mutable_path_point()->set_theta(vehicle_state.heading());
  init_point.mutable_path_point()->set_kappa(vehicle_state.kappa());

  init_point.set_v(vehicle_state.linear_velocity());
  init_point.set_a(vehicle_state.linear_acceleration());
  init_point.set_relative_time(0.0);

  DCHECK(!std::isnan(init_point.path_point().x()));
  DCHECK(!std::isnan(init_point.path_point().y()));
  DCHECK(!std::isnan(init_point.path_point().z()));
  DCHECK(!std::isnan(init_point.path_point().theta()));
  DCHECK(!std::isnan(init_point.path_point().kappa()));
  DCHECK(!std::isnan(init_point.v()));
  DCHECK(!std::isnan(init_point.a()));

  return std::vector<TrajectoryPoint>(1, init_point);
}
}  // namespace

// Planning from current vehicle state:
// if 1. the auto-driving mode is off or
//    2. we don't have the trajectory from last planning cycle or
//    3. the position deviation from actual and target is too high
std::vector<TrajectoryPoint> TrajectoryStitcher::ComputeStitchingTrajectory(
    const bool is_on_auto_mode, const double current_timestamp,
    const double planning_cycle_time,
    const PublishableTrajectory& prev_trajectory) {
  if (!is_on_auto_mode) {
    return ComputeReinitStitchingTrajectory();
  }

  std::size_t prev_trajectory_size = prev_trajectory.NumOfPoints();

  if (prev_trajectory_size == 0) {
    AWARN << "Projected trajectory at time [" << prev_trajectory.header_time()
          << "] size is zero! Previous planning not exist or failed. Use "
             "origin car status instead.";
    return ComputeReinitStitchingTrajectory();
  }

  const double veh_rel_time = current_timestamp - prev_trajectory.header_time();

  std::size_t matched_index = prev_trajectory.QueryNearestPoint(veh_rel_time);

  if (matched_index == prev_trajectory_size) {
    AWARN << "The previous trajectory is not long enough, something is wrong";
    return ComputeReinitStitchingTrajectory();
  }

  if (matched_index == 0 &&
      veh_rel_time < prev_trajectory.StartPoint().relative_time()) {
    AWARN << "the previous trajectory doesn't cover current time";
    return ComputeReinitStitchingTrajectory();
  }

  const auto& vehicle_state = *VehicleState::instance();
  auto matched_point = prev_trajectory.TrajectoryPointAt(matched_index);
  const double position_diff = std::hypot(
      matched_point.path_point().x() - vehicle_state.x(),
      matched_point.path_point().y() - vehicle_state.y());

  if (position_diff > FLAGS_replan_distance_threshold) {
    AWARN << "the distance between matched point and actual position is too "
             "large";
    return ComputeReinitStitchingTrajectory();
  }

  double forward_rel_time = veh_rel_time + planning_cycle_time;
  std::size_t forward_index =
      prev_trajectory.QueryNearestPoint(forward_rel_time);

  std::vector<TrajectoryPoint> stitching_trajectory(
      prev_trajectory.trajectory_points().begin() + matched_index,
      prev_trajectory.trajectory_points().begin() + forward_index + 1);

  const double zero_time =
      prev_trajectory.TrajectoryPointAt(matched_index).relative_time();
  const double zero_s =
      prev_trajectory.TrajectoryPointAt(forward_index).path_point().s();

  for (auto& tp : stitching_trajectory) {
    tp.set_relative_time(tp.relative_time() - zero_time);
    tp.mutable_path_point()->set_s(tp.path_point().s() - zero_s);
  }
  return stitching_trajectory;
}

}  // namespace planning
}  // namespace apollo
<commit_msg>planning: adjusted stitch zero time for more accurate time matching<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.
 *****************************************************************************/

/**
 * @file trajectory_stitcher.cc
 **/

#include "modules/planning/trajectory_stitcher/trajectory_stitcher.h"

#include <algorithm>

#include "modules/common/log.h"
#include "modules/planning/common/planning_gflags.h"
#include "modules/planning/math/double.h"

namespace apollo {
namespace planning {

using apollo::common::TrajectoryPoint;
using apollo::common::VehicleState;

namespace {

std::vector<TrajectoryPoint> ComputeReinitStitchingTrajectory() {
  TrajectoryPoint init_point;
  const auto& vehicle_state = *VehicleState::instance();
  init_point.mutable_path_point()->set_x(vehicle_state.x());
  init_point.mutable_path_point()->set_y(vehicle_state.y());
  init_point.mutable_path_point()->set_z(vehicle_state.z());
  init_point.mutable_path_point()->set_theta(vehicle_state.heading());
  init_point.mutable_path_point()->set_kappa(vehicle_state.kappa());

  init_point.set_v(vehicle_state.linear_velocity());
  init_point.set_a(vehicle_state.linear_acceleration());
  init_point.set_relative_time(0.0);

  DCHECK(!std::isnan(init_point.path_point().x()));
  DCHECK(!std::isnan(init_point.path_point().y()));
  DCHECK(!std::isnan(init_point.path_point().z()));
  DCHECK(!std::isnan(init_point.path_point().theta()));
  DCHECK(!std::isnan(init_point.path_point().kappa()));
  DCHECK(!std::isnan(init_point.v()));
  DCHECK(!std::isnan(init_point.a()));

  return std::vector<TrajectoryPoint>(1, init_point);
}
}  // namespace

// Planning from current vehicle state:
// if 1. the auto-driving mode is off or
//    2. we don't have the trajectory from last planning cycle or
//    3. the position deviation from actual and target is too high
std::vector<TrajectoryPoint> TrajectoryStitcher::ComputeStitchingTrajectory(
    const bool is_on_auto_mode, const double current_timestamp,
    const double planning_cycle_time,
    const PublishableTrajectory& prev_trajectory) {
  if (!is_on_auto_mode) {
    return ComputeReinitStitchingTrajectory();
  }

  std::size_t prev_trajectory_size = prev_trajectory.NumOfPoints();

  if (prev_trajectory_size == 0) {
    AWARN << "Projected trajectory at time [" << prev_trajectory.header_time()
          << "] size is zero! Previous planning not exist or failed. Use "
             "origin car status instead.";
    return ComputeReinitStitchingTrajectory();
  }

  const double veh_rel_time = current_timestamp - prev_trajectory.header_time();

  std::size_t matched_index = prev_trajectory.QueryNearestPoint(veh_rel_time);

  if (matched_index == prev_trajectory_size) {
    AWARN << "The previous trajectory is not long enough, something is wrong";
    return ComputeReinitStitchingTrajectory();
  }

  if (matched_index == 0 &&
      veh_rel_time < prev_trajectory.StartPoint().relative_time()) {
    AWARN << "the previous trajectory doesn't cover current time";
    return ComputeReinitStitchingTrajectory();
  }

  const auto& vehicle_state = *VehicleState::instance();
  auto matched_point = prev_trajectory.TrajectoryPointAt(matched_index);
  const double position_diff = std::hypot(
      matched_point.path_point().x() - vehicle_state.x(),
      matched_point.path_point().y() - vehicle_state.y());

  if (position_diff > FLAGS_replan_distance_threshold) {
    AWARN << "the distance between matched point and actual position is too "
             "large";
    return ComputeReinitStitchingTrajectory();
  }

  double forward_rel_time = veh_rel_time + planning_cycle_time;
  std::size_t forward_index =
      prev_trajectory.QueryNearestPoint(forward_rel_time);

  std::vector<TrajectoryPoint> stitching_trajectory(
      prev_trajectory.trajectory_points().begin() + matched_index,
      prev_trajectory.trajectory_points().begin() + forward_index + 1);

  const double zero_time = veh_rel_time;
  const double zero_s =
      prev_trajectory.TrajectoryPointAt(forward_index).path_point().s();

  for (auto& tp : stitching_trajectory) {
    tp.set_relative_time(tp.relative_time() - zero_time);
    tp.mutable_path_point()->set_s(tp.path_point().s() - zero_s);
  }
  return stitching_trajectory;
}

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


<commit_before>//===- FileCheck.cpp - Check that File's Contents match what is expected --===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// FileCheck does a line-by line check of a file that validates whether it
// contains the expected content.  This is useful for regression tests etc.
//
// This program exits with an error status of 2 on error, exit status of 0 if
// the file matched the expected contents, and exit status of 1 if it did not
// contain the expected contents.
//
//===----------------------------------------------------------------------===//

#include "llvm/Support/CommandLine.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/System/Signals.h"
using namespace llvm;

static cl::opt<std::string>
CheckFilename(cl::Positional, cl::desc("<check-file>"), cl::Required);

static cl::opt<std::string>
InputFilename("input-file", cl::desc("File to check (defaults to stdin)"),
              cl::init("-"), cl::value_desc("filename"));

static cl::opt<std::string>
CheckPrefix("check-prefix", cl::init("CHECK"),
            cl::desc("Prefix to use from check file (defaults to 'CHECK')"));

static cl::opt<bool>
NoCanonicalizeWhiteSpace("strict-whitespace",
              cl::desc("Do not treat all horizontal whitespace as equivalent"));

//===----------------------------------------------------------------------===//
// Pattern Handling Code.
//===----------------------------------------------------------------------===//

class Pattern {
  /// Str - The string to match.
  std::string Str;
public:

  Pattern() { }

  bool ParsePattern(StringRef PatternStr, SourceMgr &SM);

  /// Match - Match the pattern string against the input buffer Buffer.  This
  /// returns the position that is matched or npos if there is no match.  If
  /// there is a match, the size of the matched string is returned in MatchLen.
  size_t Match(StringRef Buffer, size_t &MatchLen) const {
    MatchLen = Str.size();
    return Buffer.find(Str);
  }

private:
  /// CanonicalizeCheckString - Replace all sequences of horizontal whitespace
  /// in the check strings with a single space.
  void CanonicalizeCheckString() {
    for (unsigned C = 0; C != Str.size(); ++C) {
      // If C is not a horizontal whitespace, skip it.
      if (Str[C] != ' ' && Str[C] != '\t')
        continue;

      // Replace the character with space, then remove any other space
      // characters after it.
      Str[C] = ' ';

      while (C+1 != Str.size() &&
             (Str[C+1] == ' ' || Str[C+1] == '\t'))
        Str.erase(Str.begin()+C+1);
    }
  }
};

bool Pattern::ParsePattern(StringRef PatternStr, SourceMgr &SM) {
  // Ignore trailing whitespace.
  while (!PatternStr.empty() &&
         (PatternStr.back() == ' ' || PatternStr.back() == '\t'))
    PatternStr = PatternStr.substr(0, PatternStr.size()-1);

  // Check that there is something on the line.
  if (PatternStr.empty()) {
    SM.PrintMessage(SMLoc::getFromPointer(PatternStr.data()),
                    "found empty check string with prefix '"+CheckPrefix+":'",
                    "error");
    return true;
  }

  Str = PatternStr.str();

  // Remove duplicate spaces in the check strings if requested.
  if (!NoCanonicalizeWhiteSpace)
    CanonicalizeCheckString();

  return false;
}

//===----------------------------------------------------------------------===//
// Check Strings.
//===----------------------------------------------------------------------===//

/// CheckString - This is a check that we found in the input file.
struct CheckString {
  /// Pat - The pattern to match.
  Pattern Pat;

  /// Loc - The location in the match file that the check string was specified.
  SMLoc Loc;

  /// IsCheckNext - This is true if this is a CHECK-NEXT: directive (as opposed
  /// to a CHECK: directive.
  bool IsCheckNext;

  /// NotStrings - These are all of the strings that are disallowed from
  /// occurring between this match string and the previous one (or start of
  /// file).
  std::vector<std::pair<SMLoc, Pattern> > NotStrings;

  CheckString(const Pattern &P, SMLoc L, bool isCheckNext)
    : Pat(P), Loc(L), IsCheckNext(isCheckNext) {}
};

/// ReadCheckFile - Read the check file, which specifies the sequence of
/// expected strings.  The strings are added to the CheckStrings vector.
static bool ReadCheckFile(SourceMgr &SM,
                          std::vector<CheckString> &CheckStrings) {
  // Open the check file, and tell SourceMgr about it.
  std::string ErrorStr;
  MemoryBuffer *F =
    MemoryBuffer::getFileOrSTDIN(CheckFilename.c_str(), &ErrorStr);
  if (F == 0) {
    errs() << "Could not open check file '" << CheckFilename << "': "
           << ErrorStr << '\n';
    return true;
  }
  SM.AddNewSourceBuffer(F, SMLoc());

  // Find all instances of CheckPrefix followed by : in the file.
  StringRef Buffer = F->getBuffer();

  std::vector<std::pair<SMLoc, Pattern> > NotMatches;

  while (1) {
    // See if Prefix occurs in the memory buffer.
    Buffer = Buffer.substr(Buffer.find(CheckPrefix));

    // If we didn't find a match, we're done.
    if (Buffer.empty())
      break;

    const char *CheckPrefixStart = Buffer.data();

    // When we find a check prefix, keep track of whether we find CHECK: or
    // CHECK-NEXT:
    bool IsCheckNext = false, IsCheckNot = false;

    // Verify that the : is present after the prefix.
    if (Buffer[CheckPrefix.size()] == ':') {
      Buffer = Buffer.substr(CheckPrefix.size()+1);
    } else if (Buffer.size() > CheckPrefix.size()+6 &&
               memcmp(Buffer.data()+CheckPrefix.size(), "-NEXT:", 6) == 0) {
      Buffer = Buffer.substr(CheckPrefix.size()+7);
      IsCheckNext = true;
    } else if (Buffer.size() > CheckPrefix.size()+5 &&
               memcmp(Buffer.data()+CheckPrefix.size(), "-NOT:", 5) == 0) {
      Buffer = Buffer.substr(CheckPrefix.size()+6);
      IsCheckNot = true;
    } else {
      Buffer = Buffer.substr(1);
      continue;
    }

    // Okay, we found the prefix, yay.  Remember the rest of the line, but
    // ignore leading and trailing whitespace.
    Buffer = Buffer.substr(Buffer.find_first_not_of(" \t"));

    // Scan ahead to the end of line.
    size_t EOL = Buffer.find_first_of("\n\r");

    // Parse the pattern.
    Pattern P;
    if (P.ParsePattern(Buffer.substr(0, EOL), SM))
      return true;

    Buffer = Buffer.substr(EOL);

    // Verify that CHECK-NEXT lines have at least one CHECK line before them.
    if (IsCheckNext && CheckStrings.empty()) {
      SM.PrintMessage(SMLoc::getFromPointer(CheckPrefixStart),
                      "found '"+CheckPrefix+"-NEXT:' without previous '"+
                      CheckPrefix+ ": line", "error");
      return true;
    }

    // Handle CHECK-NOT.
    if (IsCheckNot) {
      NotMatches.push_back(std::make_pair(SMLoc::getFromPointer(Buffer.data()),
                                          P));
      continue;
    }

    // Okay, add the string we captured to the output vector and move on.
    CheckStrings.push_back(CheckString(P,
                                       SMLoc::getFromPointer(Buffer.data()),
                                       IsCheckNext));
    std::swap(NotMatches, CheckStrings.back().NotStrings);
  }

  if (CheckStrings.empty()) {
    errs() << "error: no check strings found with prefix '" << CheckPrefix
           << ":'\n";
    return true;
  }

  if (!NotMatches.empty()) {
    errs() << "error: '" << CheckPrefix
           << "-NOT:' not supported after last check line.\n";
    return true;
  }

  return false;
}

/// CanonicalizeInputFile - Remove duplicate horizontal space from the specified
/// memory buffer, free it, and return a new one.
static MemoryBuffer *CanonicalizeInputFile(MemoryBuffer *MB) {
  SmallVector<char, 16> NewFile;
  NewFile.reserve(MB->getBufferSize());

  for (const char *Ptr = MB->getBufferStart(), *End = MB->getBufferEnd();
       Ptr != End; ++Ptr) {
    // If C is not a horizontal whitespace, skip it.
    if (*Ptr != ' ' && *Ptr != '\t') {
      NewFile.push_back(*Ptr);
      continue;
    }

    // Otherwise, add one space and advance over neighboring space.
    NewFile.push_back(' ');
    while (Ptr+1 != End &&
           (Ptr[1] == ' ' || Ptr[1] == '\t'))
      ++Ptr;
  }

  // Free the old buffer and return a new one.
  MemoryBuffer *MB2 =
    MemoryBuffer::getMemBufferCopy(NewFile.data(),
                                   NewFile.data() + NewFile.size(),
                                   MB->getBufferIdentifier());

  delete MB;
  return MB2;
}

static void PrintCheckFailed(const SourceMgr &SM, const CheckString &CheckStr,
                             StringRef Buffer) {
  // Otherwise, we have an error, emit an error message.
  SM.PrintMessage(CheckStr.Loc, "expected string not found in input",
                  "error");

  // Print the "scanning from here" line.  If the current position is at the
  // end of a line, advance to the start of the next line.
  Buffer = Buffer.substr(Buffer.find_first_not_of(" \t\n\r"));

  SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), "scanning from here",
                  "note");
}

/// CountNumNewlinesBetween - Count the number of newlines in the specified
/// range.
static unsigned CountNumNewlinesBetween(StringRef Range) {
  unsigned NumNewLines = 0;
  while (1) {
    // Scan for newline.
    Range = Range.substr(Range.find_first_of("\n\r"));
    if (Range.empty()) return NumNewLines;

    ++NumNewLines;

    // Handle \n\r and \r\n as a single newline.
    if (Range.size() > 1 &&
        (Range[1] == '\n' || Range[1] == '\r') &&
        (Range[0] != Range[1]))
      Range = Range.substr(1);
    Range = Range.substr(1);
  }
}

int main(int argc, char **argv) {
  sys::PrintStackTraceOnErrorSignal();
  PrettyStackTraceProgram X(argc, argv);
  cl::ParseCommandLineOptions(argc, argv);

  SourceMgr SM;

  // Read the expected strings from the check file.
  std::vector<CheckString> CheckStrings;
  if (ReadCheckFile(SM, CheckStrings))
    return 2;

  // Open the file to check and add it to SourceMgr.
  std::string ErrorStr;
  MemoryBuffer *F =
    MemoryBuffer::getFileOrSTDIN(InputFilename.c_str(), &ErrorStr);
  if (F == 0) {
    errs() << "Could not open input file '" << InputFilename << "': "
           << ErrorStr << '\n';
    return true;
  }

  // Remove duplicate spaces in the input file if requested.
  if (!NoCanonicalizeWhiteSpace)
    F = CanonicalizeInputFile(F);

  SM.AddNewSourceBuffer(F, SMLoc());

  // Check that we have all of the expected strings, in order, in the input
  // file.
  StringRef Buffer = F->getBuffer();

  const char *LastMatch = Buffer.data();

  for (unsigned StrNo = 0, e = CheckStrings.size(); StrNo != e; ++StrNo) {
    const CheckString &CheckStr = CheckStrings[StrNo];

    StringRef SearchFrom = Buffer;

    // Find StrNo in the file.
    size_t MatchLen = 0;
    Buffer = Buffer.substr(CheckStr.Pat.Match(Buffer, MatchLen));

    // If we didn't find a match, reject the input.
    if (Buffer.empty()) {
      PrintCheckFailed(SM, CheckStr, SearchFrom);
      return 1;
    }

    StringRef SkippedRegion(LastMatch, Buffer.data()-LastMatch);

    // If this check is a "CHECK-NEXT", verify that the previous match was on
    // the previous line (i.e. that there is one newline between them).
    if (CheckStr.IsCheckNext) {
      // Count the number of newlines between the previous match and this one.
      assert(LastMatch != F->getBufferStart() &&
             "CHECK-NEXT can't be the first check in a file");

      unsigned NumNewLines = CountNumNewlinesBetween(SkippedRegion);
      if (NumNewLines == 0) {
        SM.PrintMessage(CheckStr.Loc,
                    CheckPrefix+"-NEXT: is on the same line as previous match",
                        "error");
        SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()),
                        "'next' match was here", "note");
        SM.PrintMessage(SMLoc::getFromPointer(LastMatch),
                        "previous match was here", "note");
        return 1;
      }

      if (NumNewLines != 1) {
        SM.PrintMessage(CheckStr.Loc,
                        CheckPrefix+
                        "-NEXT: is not on the line after the previous match",
                        "error");
        SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()),
                        "'next' match was here", "note");
        SM.PrintMessage(SMLoc::getFromPointer(LastMatch),
                        "previous match was here", "note");
        return 1;
      }
    }

    // If this match had "not strings", verify that they don't exist in the
    // skipped region.
    for (unsigned i = 0, e = CheckStr.NotStrings.size(); i != e; ++i) {
      size_t MatchLen = 0;
      size_t Pos = CheckStr.NotStrings[i].second.Match(SkippedRegion, MatchLen);
      if (Pos == StringRef::npos) continue;

      SM.PrintMessage(SMLoc::getFromPointer(LastMatch+Pos),
                      CheckPrefix+"-NOT: string occurred!", "error");
      SM.PrintMessage(CheckStr.NotStrings[i].first,
                      CheckPrefix+"-NOT: pattern specified here", "note");
      return 1;
    }

    // Otherwise, everything is good.  Step over the matched text and remember
    // the position after the match as the end of the last match.
    Buffer = Buffer.substr(MatchLen);
    LastMatch = Buffer.data();
  }

  return 0;
}
<commit_msg>Use CanonicalizeInputFile to canonicalize the entire buffer containing the CHECK strings, instead of canonicalizing the patterns directly.  This allows Pattern to just contain a StringRef instead of std::string.<commit_after>//===- FileCheck.cpp - Check that File's Contents match what is expected --===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// FileCheck does a line-by line check of a file that validates whether it
// contains the expected content.  This is useful for regression tests etc.
//
// This program exits with an error status of 2 on error, exit status of 0 if
// the file matched the expected contents, and exit status of 1 if it did not
// contain the expected contents.
//
//===----------------------------------------------------------------------===//

#include "llvm/Support/CommandLine.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/System/Signals.h"
using namespace llvm;

static cl::opt<std::string>
CheckFilename(cl::Positional, cl::desc("<check-file>"), cl::Required);

static cl::opt<std::string>
InputFilename("input-file", cl::desc("File to check (defaults to stdin)"),
              cl::init("-"), cl::value_desc("filename"));

static cl::opt<std::string>
CheckPrefix("check-prefix", cl::init("CHECK"),
            cl::desc("Prefix to use from check file (defaults to 'CHECK')"));

static cl::opt<bool>
NoCanonicalizeWhiteSpace("strict-whitespace",
              cl::desc("Do not treat all horizontal whitespace as equivalent"));

//===----------------------------------------------------------------------===//
// Pattern Handling Code.
//===----------------------------------------------------------------------===//

class Pattern {
  /// Str - The string to match.
  StringRef Str;
public:

  Pattern() { }

  bool ParsePattern(StringRef PatternStr, SourceMgr &SM);

  /// Match - Match the pattern string against the input buffer Buffer.  This
  /// returns the position that is matched or npos if there is no match.  If
  /// there is a match, the size of the matched string is returned in MatchLen.
  size_t Match(StringRef Buffer, size_t &MatchLen) const {
    MatchLen = Str.size();
    return Buffer.find(Str);
  }
};

bool Pattern::ParsePattern(StringRef PatternStr, SourceMgr &SM) {
  // Ignore trailing whitespace.
  while (!PatternStr.empty() &&
         (PatternStr.back() == ' ' || PatternStr.back() == '\t'))
    PatternStr = PatternStr.substr(0, PatternStr.size()-1);

  // Check that there is something on the line.
  if (PatternStr.empty()) {
    SM.PrintMessage(SMLoc::getFromPointer(PatternStr.data()),
                    "found empty check string with prefix '"+CheckPrefix+":'",
                    "error");
    return true;
  }

  Str = PatternStr;
  return false;
}

//===----------------------------------------------------------------------===//
// Check Strings.
//===----------------------------------------------------------------------===//

/// CheckString - This is a check that we found in the input file.
struct CheckString {
  /// Pat - The pattern to match.
  Pattern Pat;

  /// Loc - The location in the match file that the check string was specified.
  SMLoc Loc;

  /// IsCheckNext - This is true if this is a CHECK-NEXT: directive (as opposed
  /// to a CHECK: directive.
  bool IsCheckNext;

  /// NotStrings - These are all of the strings that are disallowed from
  /// occurring between this match string and the previous one (or start of
  /// file).
  std::vector<std::pair<SMLoc, Pattern> > NotStrings;

  CheckString(const Pattern &P, SMLoc L, bool isCheckNext)
    : Pat(P), Loc(L), IsCheckNext(isCheckNext) {}
};

/// CanonicalizeInputFile - Remove duplicate horizontal space from the specified
/// memory buffer, free it, and return a new one.
static MemoryBuffer *CanonicalizeInputFile(MemoryBuffer *MB) {
  SmallVector<char, 16> NewFile;
  NewFile.reserve(MB->getBufferSize());

  for (const char *Ptr = MB->getBufferStart(), *End = MB->getBufferEnd();
       Ptr != End; ++Ptr) {
    // If C is not a horizontal whitespace, skip it.
    if (*Ptr != ' ' && *Ptr != '\t') {
      NewFile.push_back(*Ptr);
      continue;
    }

    // Otherwise, add one space and advance over neighboring space.
    NewFile.push_back(' ');
    while (Ptr+1 != End &&
           (Ptr[1] == ' ' || Ptr[1] == '\t'))
      ++Ptr;
  }

  // Free the old buffer and return a new one.
  MemoryBuffer *MB2 =
    MemoryBuffer::getMemBufferCopy(NewFile.data(),
                                   NewFile.data() + NewFile.size(),
                                   MB->getBufferIdentifier());

  delete MB;
  return MB2;
}

/// ReadCheckFile - Read the check file, which specifies the sequence of
/// expected strings.  The strings are added to the CheckStrings vector.
static bool ReadCheckFile(SourceMgr &SM,
                          std::vector<CheckString> &CheckStrings) {
  // Open the check file, and tell SourceMgr about it.
  std::string ErrorStr;
  MemoryBuffer *F =
    MemoryBuffer::getFileOrSTDIN(CheckFilename.c_str(), &ErrorStr);
  if (F == 0) {
    errs() << "Could not open check file '" << CheckFilename << "': "
           << ErrorStr << '\n';
    return true;
  }

  // If we want to canonicalize whitespace, strip excess whitespace from the
  // buffer containing the CHECK lines.
  if (!NoCanonicalizeWhiteSpace)
    F = CanonicalizeInputFile(F);

  SM.AddNewSourceBuffer(F, SMLoc());

  // Find all instances of CheckPrefix followed by : in the file.
  StringRef Buffer = F->getBuffer();

  std::vector<std::pair<SMLoc, Pattern> > NotMatches;

  while (1) {
    // See if Prefix occurs in the memory buffer.
    Buffer = Buffer.substr(Buffer.find(CheckPrefix));

    // If we didn't find a match, we're done.
    if (Buffer.empty())
      break;

    const char *CheckPrefixStart = Buffer.data();

    // When we find a check prefix, keep track of whether we find CHECK: or
    // CHECK-NEXT:
    bool IsCheckNext = false, IsCheckNot = false;

    // Verify that the : is present after the prefix.
    if (Buffer[CheckPrefix.size()] == ':') {
      Buffer = Buffer.substr(CheckPrefix.size()+1);
    } else if (Buffer.size() > CheckPrefix.size()+6 &&
               memcmp(Buffer.data()+CheckPrefix.size(), "-NEXT:", 6) == 0) {
      Buffer = Buffer.substr(CheckPrefix.size()+7);
      IsCheckNext = true;
    } else if (Buffer.size() > CheckPrefix.size()+5 &&
               memcmp(Buffer.data()+CheckPrefix.size(), "-NOT:", 5) == 0) {
      Buffer = Buffer.substr(CheckPrefix.size()+6);
      IsCheckNot = true;
    } else {
      Buffer = Buffer.substr(1);
      continue;
    }

    // Okay, we found the prefix, yay.  Remember the rest of the line, but
    // ignore leading and trailing whitespace.
    Buffer = Buffer.substr(Buffer.find_first_not_of(" \t"));

    // Scan ahead to the end of line.
    size_t EOL = Buffer.find_first_of("\n\r");

    // Parse the pattern.
    Pattern P;
    if (P.ParsePattern(Buffer.substr(0, EOL), SM))
      return true;

    Buffer = Buffer.substr(EOL);

    // Verify that CHECK-NEXT lines have at least one CHECK line before them.
    if (IsCheckNext && CheckStrings.empty()) {
      SM.PrintMessage(SMLoc::getFromPointer(CheckPrefixStart),
                      "found '"+CheckPrefix+"-NEXT:' without previous '"+
                      CheckPrefix+ ": line", "error");
      return true;
    }

    // Handle CHECK-NOT.
    if (IsCheckNot) {
      NotMatches.push_back(std::make_pair(SMLoc::getFromPointer(Buffer.data()),
                                          P));
      continue;
    }

    // Okay, add the string we captured to the output vector and move on.
    CheckStrings.push_back(CheckString(P,
                                       SMLoc::getFromPointer(Buffer.data()),
                                       IsCheckNext));
    std::swap(NotMatches, CheckStrings.back().NotStrings);
  }

  if (CheckStrings.empty()) {
    errs() << "error: no check strings found with prefix '" << CheckPrefix
           << ":'\n";
    return true;
  }

  if (!NotMatches.empty()) {
    errs() << "error: '" << CheckPrefix
           << "-NOT:' not supported after last check line.\n";
    return true;
  }

  return false;
}

static void PrintCheckFailed(const SourceMgr &SM, const CheckString &CheckStr,
                             StringRef Buffer) {
  // Otherwise, we have an error, emit an error message.
  SM.PrintMessage(CheckStr.Loc, "expected string not found in input",
                  "error");

  // Print the "scanning from here" line.  If the current position is at the
  // end of a line, advance to the start of the next line.
  Buffer = Buffer.substr(Buffer.find_first_not_of(" \t\n\r"));

  SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), "scanning from here",
                  "note");
}

/// CountNumNewlinesBetween - Count the number of newlines in the specified
/// range.
static unsigned CountNumNewlinesBetween(StringRef Range) {
  unsigned NumNewLines = 0;
  while (1) {
    // Scan for newline.
    Range = Range.substr(Range.find_first_of("\n\r"));
    if (Range.empty()) return NumNewLines;

    ++NumNewLines;

    // Handle \n\r and \r\n as a single newline.
    if (Range.size() > 1 &&
        (Range[1] == '\n' || Range[1] == '\r') &&
        (Range[0] != Range[1]))
      Range = Range.substr(1);
    Range = Range.substr(1);
  }
}

int main(int argc, char **argv) {
  sys::PrintStackTraceOnErrorSignal();
  PrettyStackTraceProgram X(argc, argv);
  cl::ParseCommandLineOptions(argc, argv);

  SourceMgr SM;

  // Read the expected strings from the check file.
  std::vector<CheckString> CheckStrings;
  if (ReadCheckFile(SM, CheckStrings))
    return 2;

  // Open the file to check and add it to SourceMgr.
  std::string ErrorStr;
  MemoryBuffer *F =
    MemoryBuffer::getFileOrSTDIN(InputFilename.c_str(), &ErrorStr);
  if (F == 0) {
    errs() << "Could not open input file '" << InputFilename << "': "
           << ErrorStr << '\n';
    return true;
  }

  // Remove duplicate spaces in the input file if requested.
  if (!NoCanonicalizeWhiteSpace)
    F = CanonicalizeInputFile(F);

  SM.AddNewSourceBuffer(F, SMLoc());

  // Check that we have all of the expected strings, in order, in the input
  // file.
  StringRef Buffer = F->getBuffer();

  const char *LastMatch = Buffer.data();

  for (unsigned StrNo = 0, e = CheckStrings.size(); StrNo != e; ++StrNo) {
    const CheckString &CheckStr = CheckStrings[StrNo];

    StringRef SearchFrom = Buffer;

    // Find StrNo in the file.
    size_t MatchLen = 0;
    Buffer = Buffer.substr(CheckStr.Pat.Match(Buffer, MatchLen));

    // If we didn't find a match, reject the input.
    if (Buffer.empty()) {
      PrintCheckFailed(SM, CheckStr, SearchFrom);
      return 1;
    }

    StringRef SkippedRegion(LastMatch, Buffer.data()-LastMatch);

    // If this check is a "CHECK-NEXT", verify that the previous match was on
    // the previous line (i.e. that there is one newline between them).
    if (CheckStr.IsCheckNext) {
      // Count the number of newlines between the previous match and this one.
      assert(LastMatch != F->getBufferStart() &&
             "CHECK-NEXT can't be the first check in a file");

      unsigned NumNewLines = CountNumNewlinesBetween(SkippedRegion);
      if (NumNewLines == 0) {
        SM.PrintMessage(CheckStr.Loc,
                    CheckPrefix+"-NEXT: is on the same line as previous match",
                        "error");
        SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()),
                        "'next' match was here", "note");
        SM.PrintMessage(SMLoc::getFromPointer(LastMatch),
                        "previous match was here", "note");
        return 1;
      }

      if (NumNewLines != 1) {
        SM.PrintMessage(CheckStr.Loc,
                        CheckPrefix+
                        "-NEXT: is not on the line after the previous match",
                        "error");
        SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()),
                        "'next' match was here", "note");
        SM.PrintMessage(SMLoc::getFromPointer(LastMatch),
                        "previous match was here", "note");
        return 1;
      }
    }

    // If this match had "not strings", verify that they don't exist in the
    // skipped region.
    for (unsigned i = 0, e = CheckStr.NotStrings.size(); i != e; ++i) {
      size_t MatchLen = 0;
      size_t Pos = CheckStr.NotStrings[i].second.Match(SkippedRegion, MatchLen);
      if (Pos == StringRef::npos) continue;

      SM.PrintMessage(SMLoc::getFromPointer(LastMatch+Pos),
                      CheckPrefix+"-NOT: string occurred!", "error");
      SM.PrintMessage(CheckStr.NotStrings[i].first,
                      CheckPrefix+"-NOT: pattern specified here", "note");
      return 1;
    }

    // Otherwise, everything is good.  Step over the matched text and remember
    // the position after the match as the end of the last match.
    Buffer = Buffer.substr(MatchLen);
    LastMatch = Buffer.data();
  }

  return 0;
}
<|endoftext|>


<commit_before>#include "Fullback.hpp"

#include <Constants.hpp>
#include <vector>

#include <boost/foreach.hpp>
#include <boost/make_shared.hpp>

#include "../../Window.hpp"

#include <Geometry2d/util.h>

using namespace std;

Gameplay::Behaviors::Fullback::Fullback(GameplayModule *gameplay, Side side):
	Behavior(gameplay, 1),
	_side(side)
{
}

bool Gameplay::Behaviors::Fullback::assign(set<Robot *> &available)
{
	_robots.clear();
	if (!takeBest(available))
	{
	    return false;
	}

	//Initial state
	_state = Init;

	//initialize windowevaluator
	_winEval = boost::make_shared<Gameplay::WindowEvaluator>(Behavior::gameplay()->state());
	_winEval->debug = false;

	return _robots.size() >= _minRobots;
}

bool Gameplay::Behaviors::Fullback::run()
{
	if (!assigned() || !allVisible() || !_winEval)
	{
		return false;
	}

	Geometry2d::Point ballFuture = ball().pos + ball().vel;

	//goal line, for intersection detection
	Geometry2d::Segment goalLine(Geometry2d::Point(-Constants::Field::GoalWidth / 2.0f, 0),
								  Geometry2d::Point(Constants::Field::GoalWidth / 2.0f, 0));

	// Update the target window
	_winEval->exclude.clear();
	_winEval->exclude.push_back(Behavior::robot()->pos());

	//exclude robots that arn't the fullback
	//_winEval->run(ball().pos, goalLine);

	BOOST_FOREACH(Fullback *f, otherFullbacks)
	{
		if (f->robot())
		{
			_winEval->exclude.push_back(f->robot()->pos());
		}
	}

	_winEval->run(ballFuture, goalLine);

	Window* best = 0;

	Behavior* goalie = _gameplay->goalie();

	bool needTask = false;

	//pick biggest window on appropriate side
	if (goalie && goalie->robot())
	{
		BOOST_FOREACH(Window* window, _winEval->windows)
		{
			if (_side == Left)
			{
				if (!best || window->segment.center().x < goalie->robot()->pos().x)
				{
					best = window;
				}
			}
			else if (_side == Right)
			{
				if (!best || window->segment.center().x > goalie->robot()->pos().x)
				{
					best = window;
				}
			}
		}
	}
	else
	{
		//if no side parameter...stay in the middle
		float bestDist = 0;
		BOOST_FOREACH(Window* window, _winEval->windows)
		{
			Geometry2d::Segment seg(window->segment.center(), ball().pos);
			float newDist = seg.distTo(Behavior::robot()->pos());

			if (!best || newDist < bestDist)
			{
				best = window;
				bestDist = newDist;
			}
		}
	}

	if (best && ((_side==Left&&ball().pos.x>=0) || (_side==Right&&ball().pos.x<0)))
	{
		Geometry2d::Segment shootLine(ball().pos, ball().pos + ball().vel.normalized() * 7.0);

		Geometry2d::Segment& winSeg = best->segment;

		if (ball().vel.magsq() > 0.03 && winSeg.intersects(shootLine))
		{
			robot()->move(shootLine.nearestPoint(Behavior::robot()->pos()));
			robot()->faceNone();
		}
		else
		{
			const float winSize = winSeg.length();

			if (winSize < Constants::Ball::Radius)
			{
				needTask = true;
			}
			else
			{
				const float radius = .7;

				Geometry2d::Circle arc(Geometry2d::Point(), radius);

				Geometry2d::Line shot(winSeg.center(), ballFuture);
				Geometry2d::Point dest[2];

				bool intersected = shot.intersects(arc, &dest[0], &dest[1]);

				if (intersected)
				{
					if (dest[0].y > 0)
					{
						Behavior::robot()->move(dest[0]);
					}
					else
					{
						Behavior::robot()->move(dest[1]);
					}
					Behavior::robot()->face(ballFuture);
				}
				else
				{
					needTask = true;
				}
			}
		}
	}
	else
	{
		needTask = true;
	}

	if(needTask){
		//goal line, for intersection detection
		Geometry2d::Segment goalLine(Geometry2d::Point(-Constants::Field::GoalWidth / 2.0f, 0),
									  Geometry2d::Point(Constants::Field::GoalWidth / 2.0f, 0));
		//goal arc
		const float radius = .7;
		Geometry2d::Circle arc(Geometry2d::Point(), radius);

		//opponent with ball
		Robot* oppWithBall = 0;
		float minDist = 999;
		BOOST_FOREACH(Robot *r, _gameplay->opp)
		{
			float dist = r->pos().distTo(ball().pos);
			if(dist < minDist)
			{
				minDist = dist;
				oppWithBall = r;
			}
		}
		if(oppWithBall == 0)
			return false; // need opp to block

		// block opponents that are pointed towards our goal and are on our side (left or right) and do not have the ball
		BOOST_FOREACH(Robot *r, _gameplay->opp)
		{
			if(r == oppWithBall)
				continue;

			bool sameSide = ((_side==Left&&r->pos().x<=0) || (_side==Right&&r->pos().x>=0));
			bool nonDefender = (r->pos().y < 3*Constants::Field::Length/4);
			bool facingGoal;
			Geometry2d::Point facing(cos(DegreesToRadians * r->angle()),sin(DegreesToRadians * r->angle())); // make sure not degrees!
			facing *= 20;
			Geometry2d::Segment los(facing, r->pos());
			Geometry2d::Point intr;
			facingGoal = los.intersects(goalLine,&intr);

			if(sameSide && nonDefender && facingGoal)
			{
				Geometry2d::Point dest[2];
				Geometry2d::Line losLine(facing,r->pos());
				bool ballTravelIntersects = losLine.intersects(arc, &dest[0], &dest[1]);
				if(!ballTravelIntersects)
					continue;
				Geometry2d::Point blockPoint = (dest[0].y > 0 ? dest[0] : dest[1]);
				Behavior::robot()->move(blockPoint);
				Behavior::robot()->face(r->pos());
			}
		}

	}

	return false;
}

float Gameplay::Behaviors::Fullback::score(Robot* robot)
{
	//robot closest to the back line wins
	return robot->pos().y;
}
<commit_msg>Debug prints<commit_after>#include "Fullback.hpp"

#include <Constants.hpp>
#include <vector>

#include <boost/foreach.hpp>
#include <boost/make_shared.hpp>

#include "../../Window.hpp"

#include <Geometry2d/util.h>

using namespace std;

Gameplay::Behaviors::Fullback::Fullback(GameplayModule *gameplay, Side side):
	Behavior(gameplay, 1),
	_side(side)
{
}

bool Gameplay::Behaviors::Fullback::assign(set<Robot *> &available)
{
	_robots.clear();
	if (!takeBest(available))
	{
	    return false;
	}

	//Initial state
	_state = Init;

	//initialize windowevaluator
	_winEval = boost::make_shared<Gameplay::WindowEvaluator>(Behavior::gameplay()->state());
	_winEval->debug = false;

	return _robots.size() >= _minRobots;
}

bool Gameplay::Behaviors::Fullback::run()
{
	if (!assigned() || !allVisible() || !_winEval)
	{
		return false;
	}

	Geometry2d::Point ballFuture = ball().pos + ball().vel;

	//goal line, for intersection detection
	Geometry2d::Segment goalLine(Geometry2d::Point(-Constants::Field::GoalWidth / 2.0f, 0),
								  Geometry2d::Point(Constants::Field::GoalWidth / 2.0f, 0));

	// Update the target window
	_winEval->exclude.clear();
	_winEval->exclude.push_back(Behavior::robot()->pos());

	//exclude robots that arn't the fullback
	//_winEval->run(ball().pos, goalLine);

	BOOST_FOREACH(Fullback *f, otherFullbacks)
	{
		if (f->robot())
		{
			_winEval->exclude.push_back(f->robot()->pos());
		}
	}

	_winEval->run(ballFuture, goalLine);

	Window* best = 0;

	Behavior* goalie = _gameplay->goalie();

	bool needTask = false;

	//pick biggest window on appropriate side
	if (goalie && goalie->robot())
	{
		BOOST_FOREACH(Window* window, _winEval->windows)
		{
			if (_side == Left)
			{
				if (!best || window->segment.center().x < goalie->robot()->pos().x)
				{
					best = window;
				}
			}
			else if (_side == Right)
			{
				if (!best || window->segment.center().x > goalie->robot()->pos().x)
				{
					best = window;
				}
			}
		}
	}
	else
	{
		//if no side parameter...stay in the middle
		float bestDist = 0;
		BOOST_FOREACH(Window* window, _winEval->windows)
		{
			Geometry2d::Segment seg(window->segment.center(), ball().pos);
			float newDist = seg.distTo(Behavior::robot()->pos());

			if (!best || newDist < bestDist)
			{
				best = window;
				bestDist = newDist;
			}
		}
	}

	if (best && ((_side==Left&&ball().pos.x>=0) || (_side==Right&&ball().pos.x<0)))
	{
		Geometry2d::Segment shootLine(ball().pos, ball().pos + ball().vel.normalized() * 7.0);

		Geometry2d::Segment& winSeg = best->segment;

		if (ball().vel.magsq() > 0.03 && winSeg.intersects(shootLine))
		{
			robot()->move(shootLine.nearestPoint(Behavior::robot()->pos()));
			robot()->faceNone();
		}
		else
		{
			const float winSize = winSeg.length();

			if (winSize < Constants::Ball::Radius)
			{
				needTask = true;
			}
			else
			{
				const float radius = .7;

				Geometry2d::Circle arc(Geometry2d::Point(), radius);

				Geometry2d::Line shot(winSeg.center(), ballFuture);
				Geometry2d::Point dest[2];

				bool intersected = shot.intersects(arc, &dest[0], &dest[1]);

				if (intersected)
				{
					if (dest[0].y > 0)
					{
						Behavior::robot()->move(dest[0]);
					}
					else
					{
						Behavior::robot()->move(dest[1]);
					}
					Behavior::robot()->face(ballFuture);
				}
				else
				{
					needTask = true;
				}
			}
		}
	}
	else
	{
		needTask = true;
	}

	bool debug = (robot()->id() == 3);
	if (debug) printf("\nneedTask %d\n", needTask);
	if(needTask){
		//goal line, for intersection detection
		Geometry2d::Segment goalLine(Geometry2d::Point(-Constants::Field::GoalWidth / 2.0f, 0),
									  Geometry2d::Point(Constants::Field::GoalWidth / 2.0f, 0));
		//goal arc
		const float radius = .7;
		Geometry2d::Circle arc(Geometry2d::Point(), radius);

		//opponent with ball
		Robot* oppWithBall = 0;
		float minDist = 999;
		BOOST_FOREACH(Robot *r, _gameplay->opp)
		{
			float dist = r->pos().distTo(ball().pos);
			if(dist < minDist)
			{
				minDist = dist;
				oppWithBall = r;
			}
		}
		if (debug) printf("oppWithBall %p\n", oppWithBall);
		if(oppWithBall == 0)
			return false; // need opp to block

		// block opponents that are pointed towards our goal and are on our side (left or right) and do not have the ball
		BOOST_FOREACH(Robot *r, _gameplay->opp)
		{
			if(r == oppWithBall)
				continue;

			bool sameSide = ((_side==Left&&r->pos().x<=0) || (_side==Right&&r->pos().x>=0));
			bool nonDefender = (r->pos().y < 3*Constants::Field::Length/4);
			bool facingGoal;
			Geometry2d::Point facing(cos(DegreesToRadians * r->angle()),sin(DegreesToRadians * r->angle())); // make sure not degrees!
			facing *= 20;
			Geometry2d::Segment los(facing, r->pos());
			Geometry2d::Point intr;
			facingGoal = los.intersects(goalLine,&intr);

			if (debug) printf("%d: sameSide %d nonDefender %d facingGoal %d\n", r->id(), sameSide, nonDefender, facingGoal);
			if(sameSide && nonDefender && facingGoal)
			{
				Geometry2d::Point dest[2];
				Geometry2d::Line losLine(facing,r->pos());
				bool ballTravelIntersects = losLine.intersects(arc, &dest[0], &dest[1]);
				if (debug) printf("ballTravelIntersects %d\n", ballTravelIntersects);
				if(!ballTravelIntersects)
					continue;
				Geometry2d::Point blockPoint = (dest[0].y > 0 ? dest[0] : dest[1]);
				Behavior::robot()->move(blockPoint);
				Behavior::robot()->face(r->pos());
			}
		}
	}

	return false;
}

float Gameplay::Behaviors::Fullback::score(Robot* robot)
{
	//robot closest to the back line wins
	return robot->pos().y;
}
<|endoftext|>


<commit_before>//
//  main.cpp
//  GaussianElimination
//
//  Created by Milind Chabbi on 5/14/17.
//  Copyright © 2017 Milind Chabbi. All rights reserved.
//

#include <iostream>
#define _XOPEN_SOURCE
#include <stdlib.h>
#include <vector>
#include <math.h>       /* fabs */
#include <assert.h>       /* fabs */

using namespace std;

// Given a upper triangular matrix, we back substitute to find the unknown x.
void BackSubstitute(vector< vector<double> >  & A, vector<double>  & x, vector<double>  & b, int dimension){
    const int maxRows = dimension;
    const int maxCols = dimension;

    // last row has only one unknown, hence we start from bottom up
    for(int i = maxRows-1; i >= 0 ; i--){
        double rhs = b[i];
        // solve for x[i]
        for(int j = maxCols - 1; j > i; j--){
            rhs -= A[i][j] * x[j];
        }
        x[i] = rhs / A[i][i];
    }
}

int GetMaxRow(vector< vector<double> >  & A, int piv, int dimension){
    int newPiv = piv;
    for (int i = piv; i < dimension; i ++) {
        if (fabs(A[i][piv]) > fabs(A[newPiv][piv])){
            newPiv = i;
        }
    }
    return  newPiv;
}

// Find L2 norm
double ComputeL2(vector< vector<double> >  & A, vector<double> & x, vector<double> & b, int dimension){
    int maxRows = dimension;
    int maxCols = dimension;
    vector<double>  l2Vector(dimension);

    // Compute Ax - b
    for(int i = 0 ; i < maxRows ; i++){
        l2Vector[i] = 0;
        for(int j = 0 ; j < maxCols ; j++){
            l2Vector[i] += A[i][j] * x[j];
        }
        l2Vector[i] -= b[i];
    }

    // Find sum of square of each element

    double res = 0;
    for(int i = 0 ; i < maxRows ; i++){
        res += l2Vector[i] * l2Vector[i];
    }
    // Find Square root
    return sqrt(res);
}

// Gaussian elimination with partial piviting is a method to solve a system of linear equations.
// A matlab reference implementation is here: https://www.mathworks.com/matlabcentral/fileexchange/26774-gaussian-elimination-with-partial-pivoting?focused=5147355&tab=function
// The code below is a C++ single-threaded implementation.
// The system solve Ax=b, where A is a n * n matrix, x and b are n-dimensional vectors.
// The solve phase converts A into an upper triangular matrix.
// Partial pivoting is used for numerical stability.
// The back substitution phase finds the unknowns x.
// The solution can be verified by computing the L2norm, whose value should be close to 0.
// Your task is to:
// 1. Make this code multi-threaded using OpenMP
// 2. Make this code multi-process using MPI.
// 3. Make this code multi-threaded and mylti-process via OpenMP within a node and multi-process across nodes.
// 4. Compute parallel scaling and efficiency at various thread/process counts and compare and contrast different implementations.
// Use 8000x8000 as a reference matrix for your efficiency computation.

int main(int argc, const char * argv[]) {
    // Serial case will not need workingThreads
    // Otherwise accept nthreads from commandline
    argc = 2;
    argv[1] = "1000";
    if(argc < 2){
        printf("Usage : ./%s <dimension>", argv[0]);
        return -1;
    }
    int dimension = atoi(argv[1]);
    if (dimension <= 0){
        printf("\n You should pass dimension > 0 for me to do anything useful");
        return -1;
    }

    // Solve Ax = b

    // Allocate  matrix A[dimension][dimension]
    vector< vector<double> > A(dimension);
    for(int i = 0 ; i < dimension; i++){
        A[i].resize(dimension);
    }

    // Allocate vector b[dimension]
    vector<double> b(dimension);
    // Allocate vector x[dimension]
    vector<double> x(dimension);

    // Init rand seed
    // Use this for multi-threaded
    //struct drand48_data buffer;
    //srand48_r(0, &buffer);
    srand(0);

    // Init A, b
    for(int i = 0; i < dimension; i++){
        for (int j = 0; j<dimension; j++) {
            // Not right for multi-threaded code
            A[i][j] = rand();
        }
        b[i] = rand();
    }

    for(int piv = 0 ; piv < dimension; piv ++) {
        // find pivot row
        int pivotRow = GetMaxRow(A, piv, dimension);
        // swap
        swap(A[piv], A[pivotRow]);
        swap(b[piv], b[pivotRow]);

        // Solve
        for(int i = piv+1 ; i < dimension; i++) {
            auto scale = A[i][piv] / A[piv][piv];
            for(int j = piv; j < dimension; j++){
                A[i][j] =  A[i][j] - scale * A[piv][j];
            }
            b[i] = b[i] - scale * b[piv];
        }
    }

    // Back substitute
    BackSubstitute(A, x, b, dimension);

    // Validate; l2 norm should be close to 0.
    double l2 = ComputeL2(A, x, b, dimension);
    cout<< "L2 = " << l2;
    assert (l2 < 0.01);
    return 0;
}
<commit_msg>added test macro<commit_after>//
//  main.cpp
//  GaussianElimination
//
//  Created by Milind Chabbi on 5/14/17.
//  Copyright © 2017 Milind Chabbi. All rights reserved.
//

#include <iostream>
#define _XOPEN_SOURCE
#include <stdlib.h>
#include <vector>
#include <math.h>       /* fabs */
#include <assert.h>       /* fabs */

using namespace std;

// Given a upper triangular matrix, we back substitute to find the unknown x.
void BackSubstitute(vector< vector<double> >  & A, vector<double>  & x, vector<double>  & b, int dimension){
    const int maxRows = dimension;
    const int maxCols = dimension;

    // last row has only one unknown, hence we start from bottom up
    for(int i = maxRows-1; i >= 0 ; i--){
        double rhs = b[i];
        // solve for x[i]
        for(int j = maxCols - 1; j > i; j--){
            rhs -= A[i][j] * x[j];
        }
        x[i] = rhs / A[i][i];
    }
}

int GetMaxRow(vector< vector<double> >  & A, int piv, int dimension){
    int newPiv = piv;
    for (int i = piv; i < dimension; i ++) {
        if (fabs(A[i][piv]) > fabs(A[newPiv][piv])){
            newPiv = i;
        }
    }
    return  newPiv;
}

// Find L2 norm
double ComputeL2(vector< vector<double> >  & A, vector<double> & x, vector<double> & b, int dimension){
    int maxRows = dimension;
    int maxCols = dimension;
    vector<double>  l2Vector(dimension);

    // Compute Ax - b
    for(int i = 0 ; i < maxRows ; i++){
        l2Vector[i] = 0;
        for(int j = 0 ; j < maxCols ; j++){
            l2Vector[i] += A[i][j] * x[j];
        }
        l2Vector[i] -= b[i];
    }

    // Find sum of square of each element

    double res = 0;
    for(int i = 0 ; i < maxRows ; i++){
        res += l2Vector[i] * l2Vector[i];
    }
    // Find Square root
    return sqrt(res);
}

// Gaussian elimination with partial piviting is a method to solve a system of linear equations.
// A matlab reference implementation is here: https://www.mathworks.com/matlabcentral/fileexchange/26774-gaussian-elimination-with-partial-pivoting?focused=5147355&tab=function
// The code below is a C++ single-threaded implementation.
// The system solve Ax=b, where A is a n * n matrix, x and b are n-dimensional vectors.
// The solve phase converts A into an upper triangular matrix.
// Partial pivoting is used for numerical stability.
// The back substitution phase finds the unknowns x.
// The solution can be verified by computing the L2norm, whose value should be close to 0.
// Your task is to:
// 1. Make this code multi-threaded using OpenMP
// 2. Make this code multi-process using MPI.
// 3. Make this code multi-threaded and mylti-process via OpenMP within a node and multi-process across nodes.
// 4. Compute parallel scaling and efficiency at various thread/process counts and compare and contrast different implementations.
// Use 8000x8000 as a reference matrix for your efficiency computation.

int main(int argc, const char * argv[]) {
    // Serial case will not need workingThreads
    // Otherwise accept nthreads from commandline
#ifdef TEST
    argc = 2;
    argv[1] = "1000";
#endif
    if(argc < 2){
        printf("Usage : ./%s <dimension>", argv[0]);
        return -1;
    }
    int dimension = atoi(argv[1]);
    if (dimension <= 0){
        printf("\n You should pass dimension > 0 for me to do anything useful");
        return -1;
    }

    // Solve Ax = b

    // Allocate  matrix A[dimension][dimension]
    vector< vector<double> > A(dimension);
    for(int i = 0 ; i < dimension; i++){
        A[i].resize(dimension);
    }

    // Allocate vector b[dimension]
    vector<double> b(dimension);
    // Allocate vector x[dimension]
    vector<double> x(dimension);

    // Init rand seed
    // Use this for multi-threaded
    //struct drand48_data buffer;
    //srand48_r(0, &buffer);
    srand(0);

    // Init A, b
    for(int i = 0; i < dimension; i++){
        for (int j = 0; j<dimension; j++) {
            // Not right for multi-threaded code
            A[i][j] = rand();
        }
        b[i] = rand();
    }

    for(int piv = 0 ; piv < dimension; piv ++) {
        // find pivot row
        int pivotRow = GetMaxRow(A, piv, dimension);
        // swap
        swap(A[piv], A[pivotRow]);
        swap(b[piv], b[pivotRow]);

        // Solve
        for(int i = piv+1 ; i < dimension; i++) {
            auto scale = A[i][piv] / A[piv][piv];
            for(int j = piv; j < dimension; j++){
                A[i][j] =  A[i][j] - scale * A[piv][j];
            }
            b[i] = b[i] - scale * b[piv];
        }
    }

    // Back substitute
    BackSubstitute(A, x, b, dimension);

    // Validate; l2 norm should be close to 0.
    double l2 = ComputeL2(A, x, b, dimension);
    cout<< "L2 = " << l2;
    assert (l2 < 0.01);
    return 0;
}
<|endoftext|>


<commit_before>//===--- Triple.cpp - Target triple helper class --------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "llvm/ADT/Triple.h"

#include "llvm/ADT/Twine.h"
#include <cassert>
#include <cstring>
using namespace llvm;

//

const char *Triple::getArchTypeName(ArchType Kind) {
  switch (Kind) {
  case InvalidArch: return "<invalid>";
  case UnknownArch: return "unknown";

  case alpha:   return "alpha";
  case arm:     return "arm";
  case bfin:    return "bfin";
  case cellspu: return "cellspu";
  case mips:    return "mips";
  case mipsel:  return "mipsel";
  case msp430:  return "msp430";
  case pic16:   return "pic16";
  case ppc64:   return "powerpc64";
  case ppc:     return "powerpc";
  case sparc:   return "sparc";
  case systemz: return "s390x";
  case tce:     return "tce";
  case thumb:   return "thumb";
  case x86:     return "i386";
  case x86_64:  return "x86_64";
  case xcore:   return "xcore";
  }

  return "<invalid>";
}

const char *Triple::getArchTypePrefix(ArchType Kind) {
  switch (Kind) {
  default:
    return 0;

  case alpha:   return "alpha";

  case arm:
  case thumb:   return "arm";

  case bfin:    return "bfin";

  case cellspu: return "spu";

  case ppc64:
  case ppc:     return "ppc";

  case sparc:   return "sparc";

  case x86:
  case x86_64:  return "x86";
  case xcore:   return "xcore";
  }
}

const char *Triple::getVendorTypeName(VendorType Kind) {
  switch (Kind) {
  case UnknownVendor: return "unknown";

  case Apple: return "apple";
  case PC: return "pc";
  }

  return "<invalid>";
}

const char *Triple::getOSTypeName(OSType Kind) {
  switch (Kind) {
  case UnknownOS: return "unknown";

  case AuroraUX: return "auroraux";
  case Cygwin: return "cygwin";
  case Darwin: return "darwin";
  case DragonFly: return "dragonfly";
  case FreeBSD: return "freebsd";
  case Linux: return "linux";
  case MinGW32: return "mingw32";
  case MinGW64: return "mingw64";
  case NetBSD: return "netbsd";
  case OpenBSD: return "openbsd";
  case Solaris: return "solaris";
  case Win32: return "win32";
  }

  return "<invalid>";
}

Triple::ArchType Triple::getArchTypeForLLVMName(const StringRef &Name) {
  if (Name == "alpha")
    return alpha;
  if (Name == "arm")
    return arm;
  if (Name == "bfin")
    return bfin;
  if (Name == "cellspu")
    return cellspu;
  if (Name == "mips")
    return mips;
  if (Name == "mipsel")
    return mipsel;
  if (Name == "msp430")
    return msp430;
  if (Name == "pic16")
    return pic16;
  if (Name == "ppc64")
    return ppc64;
  if (Name == "ppc")
    return ppc;
  if (Name == "sparc")
    return sparc;
  if (Name == "systemz")
    return systemz;
  if (Name == "tce")
    return tce;
  if (Name == "thumb")
    return thumb;
  if (Name == "x86")
    return x86;
  if (Name == "x86-64")
    return x86_64;
  if (Name == "xcore")
    return xcore;

  return UnknownArch;
}

Triple::ArchType Triple::getArchTypeForDarwinArchName(const StringRef &Str) {
  // See arch(3) and llvm-gcc's driver-driver.c. We don't implement support for
  // archs which Darwin doesn't use.

  // The matching this routine does is fairly pointless, since it is neither the
  // complete architecture list, nor a reasonable subset. The problem is that
  // historically the driver driver accepts this and also ties its -march=
  // handling to the architecture name, so we need to be careful before removing
  // support for it.

  // This code must be kept in sync with Clang's Darwin specific argument
  // translation.

  if (Str == "ppc" || Str == "ppc601" || Str == "ppc603" || Str == "ppc604" ||
      Str == "ppc604e" || Str == "ppc750" || Str == "ppc7400" ||
      Str == "ppc7450" || Str == "ppc970")
    return Triple::ppc;

  if (Str == "ppc64")
    return Triple::ppc64;

  if (Str == "i386" || Str == "i486" || Str == "i486SX" || Str == "pentium" ||
      Str == "i586" || Str == "pentpro" || Str == "i686" || Str == "pentIIm3" ||
      Str == "pentIIm5" || Str == "pentium4")
    return Triple::x86;

  if (Str == "x86_64")
    return Triple::x86_64;

  // This is derived from the driver driver.
  if (Str == "arm" || Str == "armv4t" || Str == "armv5" || Str == "xscale" ||
      Str == "armv6" || Str == "armv7")
    return Triple::arm;

  return Triple::UnknownArch;
}

//

void Triple::Parse() const {
  assert(!isInitialized() && "Invalid parse call.");

  StringRef ArchName = getArchName();
  StringRef VendorName = getVendorName();
  StringRef OSName = getOSName();

  if (ArchName.size() == 4 && ArchName[0] == 'i' &&
      ArchName[2] == '8' && ArchName[3] == '6' &&
      ArchName[1] - '3' < 6) // i[3-9]86
    Arch = x86;
  else if (ArchName == "amd64" || ArchName == "x86_64")
    Arch = x86_64;
  else if (ArchName == "bfin")
    Arch = bfin;
  else if (ArchName == "pic16")
    Arch = pic16;
  else if (ArchName == "powerpc")
    Arch = ppc;
  else if (ArchName == "powerpc64")
    Arch = ppc64;
  else if (ArchName == "arm" ||
           ArchName.startswith("armv") ||
           ArchName == "xscale")
    Arch = arm;
  else if (ArchName == "thumb" ||
           ArchName.startswith("thumbv"))
    Arch = thumb;
  else if (ArchName.startswith("alpha"))
    Arch = alpha;
  else if (ArchName == "spu" || ArchName == "cellspu")
    Arch = cellspu;
  else if (ArchName == "msp430")
    Arch = msp430;
  else if (ArchName == "mips" || ArchName == "mipsallegrex")
    Arch = mips;
  else if (ArchName == "mipsel" || ArchName == "mipsallegrexel" ||
           ArchName == "psp")
    Arch = mipsel;
  else if (ArchName == "sparc")
    Arch = sparc;
  else if (ArchName == "s390x")
    Arch = systemz;
  else if (ArchName == "tce")
    Arch = tce;
  else if (ArchName == "xcore")
    Arch = xcore;
  else
    Arch = UnknownArch;

  // Handle some exceptional cases where the OS / environment components are
  // stuck into the vendor field.
  if (StringRef(getTriple()).count('-') == 1) {
    StringRef VendorName = getVendorName();

    if (VendorName.startswith("mingw32")) { // 'i386-mingw32', etc.
      Vendor = PC;
      OS = MinGW32;
      return;
    }

    // arm-elf is another example, but we don't currently parse anything about
    // the environment.
  }

  if (VendorName == "apple")
    Vendor = Apple;
  else if (VendorName == "pc")
    Vendor = PC;
  else
    Vendor = UnknownVendor;

  if (OSName.startswith("auroraux"))
    OS = AuroraUX;
  else if (OSName.startswith("cygwin"))
    OS = Cygwin;
  else if (OSName.startswith("darwin"))
    OS = Darwin;
  else if (OSName.startswith("dragonfly"))
    OS = DragonFly;
  else if (OSName.startswith("freebsd"))
    OS = FreeBSD;
  else if (OSName.startswith("linux"))
    OS = Linux;
  else if (OSName.startswith("mingw32"))
    OS = MinGW32;
  else if (OSName.startswith("mingw64"))
    OS = MinGW64;
  else if (OSName.startswith("netbsd"))
    OS = NetBSD;
  else if (OSName.startswith("openbsd"))
    OS = OpenBSD;
  else if (OSName.startswith("solaris"))
    OS = Solaris;
  else if (OSName.startswith("win32"))
    OS = Win32;
  else
    OS = UnknownOS;

  assert(isInitialized() && "Failed to initialize!");
}

StringRef Triple::getArchName() const {
  return StringRef(Data).split('-').first;           // Isolate first component
}

StringRef Triple::getVendorName() const {
  StringRef Tmp = StringRef(Data).split('-').second; // Strip first component
  return Tmp.split('-').first;                       // Isolate second component
}

StringRef Triple::getOSName() const {
  StringRef Tmp = StringRef(Data).split('-').second; // Strip first component
  Tmp = Tmp.split('-').second;                       // Strip second component
  return Tmp.split('-').first;                       // Isolate third component
}

StringRef Triple::getEnvironmentName() const {
  StringRef Tmp = StringRef(Data).split('-').second; // Strip first component
  Tmp = Tmp.split('-').second;                       // Strip second component
  return Tmp.split('-').second;                      // Strip third component
}

StringRef Triple::getOSAndEnvironmentName() const {
  StringRef Tmp = StringRef(Data).split('-').second; // Strip first component
  return Tmp.split('-').second;                      // Strip second component
}

static unsigned EatNumber(StringRef &Str) {
  assert(!Str.empty() && Str[0] >= '0' && Str[0] <= '9' && "Not a number");
  unsigned Result = Str[0]-'0';

  // Eat the digit.
  Str = Str.substr(1);

  // Handle "darwin11".
  if (Result == 1 && !Str.empty() && Str[0] >= '0' && Str[0] <= '9') {
    Result = Result*10 + (Str[0] - '0');
    // Eat the digit.
    Str = Str.substr(1);
  }

  return Result;
}

/// getDarwinNumber - Parse the 'darwin number' out of the specific target
/// triple.  For example, if we have darwin8.5 return 8,5,0.  If any entry is
/// not defined, return 0's.  This requires that the triple have an OSType of
/// darwin before it is called.
void Triple::getDarwinNumber(unsigned &Maj, unsigned &Min,
                             unsigned &Revision) const {
  assert(getOS() == Darwin && "Not a darwin target triple!");
  StringRef OSName = getOSName();
  assert(OSName.startswith("darwin") && "Unknown darwin target triple!");

  // Strip off "darwin".
  OSName = OSName.substr(6);

  Maj = Min = Revision = 0;

  if (OSName.empty() || OSName[0] < '0' || OSName[0] > '9')
    return;

  // The major version is the first digit.
  Maj = EatNumber(OSName);
  if (OSName.empty()) return;

  // Handle minor version: 10.4.9 -> darwin8.9.
  if (OSName[0] != '.')
    return;

  // Eat the '.'.
  OSName = OSName.substr(1);

  if (OSName.empty() || OSName[0] < '0' || OSName[0] > '9')
    return;

  Min = EatNumber(OSName);
  if (OSName.empty()) return;

  // Handle revision darwin8.9.1
  if (OSName[0] != '.')
    return;

  // Eat the '.'.
  OSName = OSName.substr(1);

  if (OSName.empty() || OSName[0] < '0' || OSName[0] > '9')
    return;

  Revision = EatNumber(OSName);
}

void Triple::setTriple(const Twine &Str) {
  Data = Str.str();
  Arch = InvalidArch;
}

void Triple::setArch(ArchType Kind) {
  setArchName(getArchTypeName(Kind));
}

void Triple::setVendor(VendorType Kind) {
  setVendorName(getVendorTypeName(Kind));
}

void Triple::setOS(OSType Kind) {
  setOSName(getOSTypeName(Kind));
}

void Triple::setArchName(const StringRef &Str) {
  // Work around a miscompilation bug in gcc 4.0.3.
  Twine a = getVendorName() + "-" + getOSAndEnvironmentName();
  Twine b = Str + "-" + a;
  setTriple(b);
}

void Triple::setVendorName(const StringRef &Str) {
  setTriple(getArchName() + "-" + Str + "-" + getOSAndEnvironmentName());
}

void Triple::setOSName(const StringRef &Str) {
  if (hasEnvironment())
    setTriple(getArchName() + "-" + getVendorName() + "-" + Str +
              "-" + getEnvironmentName());
  else
    setTriple(getArchName() + "-" + getVendorName() + "-" + Str);
}

void Triple::setEnvironmentName(const StringRef &Str) {
  setTriple(getArchName() + "-" + getVendorName() + "-" + getOSName() +
            "-" + Str);
}

void Triple::setOSAndEnvironmentName(const StringRef &Str) {
  setTriple(getArchName() + "-" + getVendorName() + "-" + Str);
}
<commit_msg>r83391 was completely broken since Twines keep references to their inputs, and some of the inputs were temporaries.  Here's a real fix for the miscompilation. Thanks to sabre for pointing out the problem.<commit_after>//===--- Triple.cpp - Target triple helper class --------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "llvm/ADT/Triple.h"

#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/Twine.h"
#include <cassert>
#include <cstring>
using namespace llvm;

//

const char *Triple::getArchTypeName(ArchType Kind) {
  switch (Kind) {
  case InvalidArch: return "<invalid>";
  case UnknownArch: return "unknown";

  case alpha:   return "alpha";
  case arm:     return "arm";
  case bfin:    return "bfin";
  case cellspu: return "cellspu";
  case mips:    return "mips";
  case mipsel:  return "mipsel";
  case msp430:  return "msp430";
  case pic16:   return "pic16";
  case ppc64:   return "powerpc64";
  case ppc:     return "powerpc";
  case sparc:   return "sparc";
  case systemz: return "s390x";
  case tce:     return "tce";
  case thumb:   return "thumb";
  case x86:     return "i386";
  case x86_64:  return "x86_64";
  case xcore:   return "xcore";
  }

  return "<invalid>";
}

const char *Triple::getArchTypePrefix(ArchType Kind) {
  switch (Kind) {
  default:
    return 0;

  case alpha:   return "alpha";

  case arm:
  case thumb:   return "arm";

  case bfin:    return "bfin";

  case cellspu: return "spu";

  case ppc64:
  case ppc:     return "ppc";

  case sparc:   return "sparc";

  case x86:
  case x86_64:  return "x86";
  case xcore:   return "xcore";
  }
}

const char *Triple::getVendorTypeName(VendorType Kind) {
  switch (Kind) {
  case UnknownVendor: return "unknown";

  case Apple: return "apple";
  case PC: return "pc";
  }

  return "<invalid>";
}

const char *Triple::getOSTypeName(OSType Kind) {
  switch (Kind) {
  case UnknownOS: return "unknown";

  case AuroraUX: return "auroraux";
  case Cygwin: return "cygwin";
  case Darwin: return "darwin";
  case DragonFly: return "dragonfly";
  case FreeBSD: return "freebsd";
  case Linux: return "linux";
  case MinGW32: return "mingw32";
  case MinGW64: return "mingw64";
  case NetBSD: return "netbsd";
  case OpenBSD: return "openbsd";
  case Solaris: return "solaris";
  case Win32: return "win32";
  }

  return "<invalid>";
}

Triple::ArchType Triple::getArchTypeForLLVMName(const StringRef &Name) {
  if (Name == "alpha")
    return alpha;
  if (Name == "arm")
    return arm;
  if (Name == "bfin")
    return bfin;
  if (Name == "cellspu")
    return cellspu;
  if (Name == "mips")
    return mips;
  if (Name == "mipsel")
    return mipsel;
  if (Name == "msp430")
    return msp430;
  if (Name == "pic16")
    return pic16;
  if (Name == "ppc64")
    return ppc64;
  if (Name == "ppc")
    return ppc;
  if (Name == "sparc")
    return sparc;
  if (Name == "systemz")
    return systemz;
  if (Name == "tce")
    return tce;
  if (Name == "thumb")
    return thumb;
  if (Name == "x86")
    return x86;
  if (Name == "x86-64")
    return x86_64;
  if (Name == "xcore")
    return xcore;

  return UnknownArch;
}

Triple::ArchType Triple::getArchTypeForDarwinArchName(const StringRef &Str) {
  // See arch(3) and llvm-gcc's driver-driver.c. We don't implement support for
  // archs which Darwin doesn't use.

  // The matching this routine does is fairly pointless, since it is neither the
  // complete architecture list, nor a reasonable subset. The problem is that
  // historically the driver driver accepts this and also ties its -march=
  // handling to the architecture name, so we need to be careful before removing
  // support for it.

  // This code must be kept in sync with Clang's Darwin specific argument
  // translation.

  if (Str == "ppc" || Str == "ppc601" || Str == "ppc603" || Str == "ppc604" ||
      Str == "ppc604e" || Str == "ppc750" || Str == "ppc7400" ||
      Str == "ppc7450" || Str == "ppc970")
    return Triple::ppc;

  if (Str == "ppc64")
    return Triple::ppc64;

  if (Str == "i386" || Str == "i486" || Str == "i486SX" || Str == "pentium" ||
      Str == "i586" || Str == "pentpro" || Str == "i686" || Str == "pentIIm3" ||
      Str == "pentIIm5" || Str == "pentium4")
    return Triple::x86;

  if (Str == "x86_64")
    return Triple::x86_64;

  // This is derived from the driver driver.
  if (Str == "arm" || Str == "armv4t" || Str == "armv5" || Str == "xscale" ||
      Str == "armv6" || Str == "armv7")
    return Triple::arm;

  return Triple::UnknownArch;
}

//

void Triple::Parse() const {
  assert(!isInitialized() && "Invalid parse call.");

  StringRef ArchName = getArchName();
  StringRef VendorName = getVendorName();
  StringRef OSName = getOSName();

  if (ArchName.size() == 4 && ArchName[0] == 'i' &&
      ArchName[2] == '8' && ArchName[3] == '6' &&
      ArchName[1] - '3' < 6) // i[3-9]86
    Arch = x86;
  else if (ArchName == "amd64" || ArchName == "x86_64")
    Arch = x86_64;
  else if (ArchName == "bfin")
    Arch = bfin;
  else if (ArchName == "pic16")
    Arch = pic16;
  else if (ArchName == "powerpc")
    Arch = ppc;
  else if (ArchName == "powerpc64")
    Arch = ppc64;
  else if (ArchName == "arm" ||
           ArchName.startswith("armv") ||
           ArchName == "xscale")
    Arch = arm;
  else if (ArchName == "thumb" ||
           ArchName.startswith("thumbv"))
    Arch = thumb;
  else if (ArchName.startswith("alpha"))
    Arch = alpha;
  else if (ArchName == "spu" || ArchName == "cellspu")
    Arch = cellspu;
  else if (ArchName == "msp430")
    Arch = msp430;
  else if (ArchName == "mips" || ArchName == "mipsallegrex")
    Arch = mips;
  else if (ArchName == "mipsel" || ArchName == "mipsallegrexel" ||
           ArchName == "psp")
    Arch = mipsel;
  else if (ArchName == "sparc")
    Arch = sparc;
  else if (ArchName == "s390x")
    Arch = systemz;
  else if (ArchName == "tce")
    Arch = tce;
  else if (ArchName == "xcore")
    Arch = xcore;
  else
    Arch = UnknownArch;

  // Handle some exceptional cases where the OS / environment components are
  // stuck into the vendor field.
  if (StringRef(getTriple()).count('-') == 1) {
    StringRef VendorName = getVendorName();

    if (VendorName.startswith("mingw32")) { // 'i386-mingw32', etc.
      Vendor = PC;
      OS = MinGW32;
      return;
    }

    // arm-elf is another example, but we don't currently parse anything about
    // the environment.
  }

  if (VendorName == "apple")
    Vendor = Apple;
  else if (VendorName == "pc")
    Vendor = PC;
  else
    Vendor = UnknownVendor;

  if (OSName.startswith("auroraux"))
    OS = AuroraUX;
  else if (OSName.startswith("cygwin"))
    OS = Cygwin;
  else if (OSName.startswith("darwin"))
    OS = Darwin;
  else if (OSName.startswith("dragonfly"))
    OS = DragonFly;
  else if (OSName.startswith("freebsd"))
    OS = FreeBSD;
  else if (OSName.startswith("linux"))
    OS = Linux;
  else if (OSName.startswith("mingw32"))
    OS = MinGW32;
  else if (OSName.startswith("mingw64"))
    OS = MinGW64;
  else if (OSName.startswith("netbsd"))
    OS = NetBSD;
  else if (OSName.startswith("openbsd"))
    OS = OpenBSD;
  else if (OSName.startswith("solaris"))
    OS = Solaris;
  else if (OSName.startswith("win32"))
    OS = Win32;
  else
    OS = UnknownOS;

  assert(isInitialized() && "Failed to initialize!");
}

StringRef Triple::getArchName() const {
  return StringRef(Data).split('-').first;           // Isolate first component
}

StringRef Triple::getVendorName() const {
  StringRef Tmp = StringRef(Data).split('-').second; // Strip first component
  return Tmp.split('-').first;                       // Isolate second component
}

StringRef Triple::getOSName() const {
  StringRef Tmp = StringRef(Data).split('-').second; // Strip first component
  Tmp = Tmp.split('-').second;                       // Strip second component
  return Tmp.split('-').first;                       // Isolate third component
}

StringRef Triple::getEnvironmentName() const {
  StringRef Tmp = StringRef(Data).split('-').second; // Strip first component
  Tmp = Tmp.split('-').second;                       // Strip second component
  return Tmp.split('-').second;                      // Strip third component
}

StringRef Triple::getOSAndEnvironmentName() const {
  StringRef Tmp = StringRef(Data).split('-').second; // Strip first component
  return Tmp.split('-').second;                      // Strip second component
}

static unsigned EatNumber(StringRef &Str) {
  assert(!Str.empty() && Str[0] >= '0' && Str[0] <= '9' && "Not a number");
  unsigned Result = Str[0]-'0';

  // Eat the digit.
  Str = Str.substr(1);

  // Handle "darwin11".
  if (Result == 1 && !Str.empty() && Str[0] >= '0' && Str[0] <= '9') {
    Result = Result*10 + (Str[0] - '0');
    // Eat the digit.
    Str = Str.substr(1);
  }

  return Result;
}

/// getDarwinNumber - Parse the 'darwin number' out of the specific target
/// triple.  For example, if we have darwin8.5 return 8,5,0.  If any entry is
/// not defined, return 0's.  This requires that the triple have an OSType of
/// darwin before it is called.
void Triple::getDarwinNumber(unsigned &Maj, unsigned &Min,
                             unsigned &Revision) const {
  assert(getOS() == Darwin && "Not a darwin target triple!");
  StringRef OSName = getOSName();
  assert(OSName.startswith("darwin") && "Unknown darwin target triple!");

  // Strip off "darwin".
  OSName = OSName.substr(6);

  Maj = Min = Revision = 0;

  if (OSName.empty() || OSName[0] < '0' || OSName[0] > '9')
    return;

  // The major version is the first digit.
  Maj = EatNumber(OSName);
  if (OSName.empty()) return;

  // Handle minor version: 10.4.9 -> darwin8.9.
  if (OSName[0] != '.')
    return;

  // Eat the '.'.
  OSName = OSName.substr(1);

  if (OSName.empty() || OSName[0] < '0' || OSName[0] > '9')
    return;

  Min = EatNumber(OSName);
  if (OSName.empty()) return;

  // Handle revision darwin8.9.1
  if (OSName[0] != '.')
    return;

  // Eat the '.'.
  OSName = OSName.substr(1);

  if (OSName.empty() || OSName[0] < '0' || OSName[0] > '9')
    return;

  Revision = EatNumber(OSName);
}

void Triple::setTriple(const Twine &Str) {
  Data = Str.str();
  Arch = InvalidArch;
}

void Triple::setArch(ArchType Kind) {
  setArchName(getArchTypeName(Kind));
}

void Triple::setVendor(VendorType Kind) {
  setVendorName(getVendorTypeName(Kind));
}

void Triple::setOS(OSType Kind) {
  setOSName(getOSTypeName(Kind));
}

void Triple::setArchName(const StringRef &Str) {
  // Work around a miscompilation bug for Twines in gcc 4.0.3.
  SmallString<64> Triple;
  Triple += Str;
  Triple += "-";
  Triple += getVendorName();
  Triple += "-";
  Triple += getOSAndEnvironmentName();
  setTriple(Triple.str());
}

void Triple::setVendorName(const StringRef &Str) {
  setTriple(getArchName() + "-" + Str + "-" + getOSAndEnvironmentName());
}

void Triple::setOSName(const StringRef &Str) {
  if (hasEnvironment())
    setTriple(getArchName() + "-" + getVendorName() + "-" + Str +
              "-" + getEnvironmentName());
  else
    setTriple(getArchName() + "-" + getVendorName() + "-" + Str);
}

void Triple::setEnvironmentName(const StringRef &Str) {
  setTriple(getArchName() + "-" + getVendorName() + "-" + getOSName() +
            "-" + Str);
}

void Triple::setOSAndEnvironmentName(const StringRef &Str) {
  setTriple(getArchName() + "-" + getVendorName() + "-" + Str);
}
<|endoftext|>