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

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.

     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.

=========================================================================*/
#include "otbDSFuzzyModelEstimation.h"

#include <iostream>
#include "otbCommandLineArgumentParser.h"

#include "otbVectorData.h"
#include "otbVectorDataFileReader.h"
#include "otbVectorDataFileWriter.h"
#include "otbImageToEnvelopeVectorDataFilter.h"
#include "otbVectorDataToRandomLineGenerator.h"
#include "itkAmoebaOptimizer.h"
#include "otbVectorDataToDSValidatedVectorDataFilter.h"
#include "otbStandardDSCostFunction.h"
#include "otbFuzzyDescriptorsModelManager.h"

//  The following piece of code implements an observer
//  that will monitor the evolution of the registration process.
#include "itkCommand.h"
class CommandIterationUpdate : public itk::Command
{
public:
typedef  CommandIterationUpdate   Self;
typedef  itk::Command             Superclass;
typedef itk::SmartPointer<Self>   Pointer;
itkNewMacro( Self );
protected:
CommandIterationUpdate() {};
public:
typedef itk::AmoebaOptimizer         OptimizerType;
typedef   const OptimizerType   *    OptimizerPointer;

void Execute(itk::Object *caller, const itk::EventObject & event)
{
  Execute( (const itk::Object *)caller, event);
}

void Execute(const itk::Object * object, const itk::EventObject & event)
{
  OptimizerPointer optimizer =
      dynamic_cast< OptimizerPointer >( object );
  if( ! itk::IterationEvent().CheckEvent( &event ) )
    {
    return;
    }
  std::cout << optimizer->GetCachedValue() << "   ";
  std::cout << optimizer->GetCachedCurrentPosition() << std::endl;
}
};

//namespace otb
//{

int otb::DSFuzzyModelEstimation::Describe(ApplicationDescriptor* descriptor)
{
  descriptor->SetName("DSFuzzyModelEstimation");
  descriptor->SetDescription("Estimate feature fuzzy model parameters using 2 vector data (ground truth samples and wrong samples)");
  descriptor->AddOption("InputPositiveVectorData", "Ground truth vector data",
                        "psin", 1, true, ApplicationDescriptor::FileName);
  descriptor->AddOption("InputNegativeVectorData", "Negative samples vector data",
                        "nsin", 1, true, ApplicationDescriptor::FileName);
  descriptor->AddOptionNParams("BeliefSupport", "Dempster Shafer study hypothesis to compute belief",
                               "BelSup", true, ApplicationDescriptor::StringList);
  descriptor->AddOptionNParams("PlausibilitySupport", "Dempster Shafer study hypothesis to compute plausibility",
                               "PlaSup", true, ApplicationDescriptor::StringList);
  descriptor->AddOption("Criterion", "Dempster Shafer criterion (by default (belief+plausibility)/2)",
                        "cri", 1, false, ApplicationDescriptor::String);
  descriptor->AddOption("Weighting", "Coefficient between 0 and 1 to promote undetection or false detections (default 0.5)",
                        "wgt", 1, false, ApplicationDescriptor::Real);
  descriptor->AddOption("InitModel", "Initial state for the model Optimizer",
                        "InitMod", 1, false, ApplicationDescriptor::FileName);
  descriptor->AddOptionNParams("DescriptorList", "List of the descriptors used in the model (must be specified to perform an automatic initialization)",
                        "DescList", false, ApplicationDescriptor::StringList);
  descriptor->AddOption("MaximumNumberOfIterations", "Maximum number of optimizer iteration (default 200)",
                        "MaxNbIt", 1, false, ApplicationDescriptor::Integer);
  descriptor->AddOption("OptimizerObserver", "Activate or not the optimizer observer",
                        "OptObs", 0, false, ApplicationDescriptor::Boolean);
  descriptor->AddOption("Output", "Output model file name (xml file)",
                        "out", 1,  true, ApplicationDescriptor::FileName);

  return EXIT_SUCCESS;
}

int otb::DSFuzzyModelEstimation::Execute(otb::ApplicationOptionsResult* parseResult)
{
  typedef otb::VectorData<double>                     VectorDataType;
  typedef VectorDataType::ValuePrecisionType          PrecisionType;
  typedef VectorDataType::PrecisionType               CoordRepType;
  typedef otb::VectorDataFileReader<VectorDataType>   VectorDataReaderType;

  typedef otb::VectorDataToDSValidatedVectorDataFilter<VectorDataType, PrecisionType>
                                                      ValidationFilterType;
  typedef otb::StandardDSCostFunction<ValidationFilterType> CostFunctionType;
  typedef CostFunctionType::LabelSetType              LabelSetType;

  typedef itk::AmoebaOptimizer                        OptimizerType;

  typedef otb::FuzzyDescriptorsModelManager::DescriptorsModelType
                                                      DescriptorsModelType;
  typedef otb::FuzzyDescriptorsModelManager::DescriptorListType
                                                      DescriptorListType;
  //Instantiate
  VectorDataReaderType::Pointer               psReader = VectorDataReaderType::New();
  VectorDataReaderType::Pointer               nsReader = VectorDataReaderType::New();
  CostFunctionType::Pointer                   costFunction = CostFunctionType::New();
  OptimizerType::Pointer                      optimizer = OptimizerType::New();

  if ((parseResult->IsOptionPresent("DescriptorList") && parseResult->IsOptionPresent("InitModel"))
      || (!parseResult->IsOptionPresent("DescriptorList") && !parseResult->IsOptionPresent("InitModel")))
    {
    std::cout << "ERROR: An Initial Model OR a Descriptor List must be specified (but not both)" << std::endl;
    return EXIT_FAILURE;
    }

  //Read the vector datas
  psReader->SetFileName(parseResult->GetParameterString("InputPositiveVectorData"));
  psReader->Update();

  nsReader->SetFileName(parseResult->GetParameterString("InputNegativeVectorData"));
  nsReader->Update();

  // Load the initial descriptor model
  DescriptorListType   descList;
  DescriptorsModelType descMod;
  if (parseResult->IsOptionPresent("InitModel"))
    {
    std::string descModFile = parseResult->GetParameterString("InitModel");
    descMod  = FuzzyDescriptorsModelManager::Read( descModFile.c_str() );
    descList = FuzzyDescriptorsModelManager::GetDescriptorList(descMod);
    }
  else
    {
    int nbsdDesc = parseResult->GetNumberOfParameters("DescriptorList");
    for (int i = 0; i < nbsdDesc; i++)
        {
        descList.push_back(parseResult->GetParameterString("DescriptorList", i));
        }
    }
  costFunction->SetDescriptorList(descList);

  // Compute statistics of all the descriptors
  typedef VectorDataType::DataTreeType DataTreeType;
  typedef VectorDataType::DataNodeType DataNodeType;
  typedef itk::PreOrderTreeIterator<VectorDataType::DataTreeType>
  TreeIteratorType;

  std::vector<double> accFirstOrderPS, accSecondOrderPS, minPS, maxPS;
  accFirstOrderPS.resize(descList.size());
  accSecondOrderPS.resize(descList.size());
  std::fill(accFirstOrderPS.begin(), accFirstOrderPS.end(), 0);
  std::fill(accSecondOrderPS.begin(), accSecondOrderPS.end(), 0);
  minPS.resize(descList.size());
  maxPS.resize(descList.size());
  unsigned int accNbElemPS = 0;

  TreeIteratorType itVectorPS(psReader->GetOutput()->GetDataTree());
  for( itVectorPS.GoToBegin(); !itVectorPS.IsAtEnd(); ++itVectorPS )
    {
    if (!itVectorPS.Get()->IsRoot()
        && !itVectorPS.Get()->IsDocument()
        && !itVectorPS.Get()->IsFolder())
      {
      DataNodeType::Pointer currentGeometry = itVectorPS.Get();

      for (unsigned int i = 0; i < descList.size(); ++i)
        {
        double desc = currentGeometry->GetFieldAsDouble(descList[i]);

        accFirstOrderPS[i] += desc;
        accSecondOrderPS[i] += desc * desc;

        if (desc < minPS[i])
          {
          minPS[i] = desc;
          }
        if (desc > maxPS[i])
          {
          maxPS[i] = desc;
          }

        }
      accNbElemPS ++;
      }
    }

  TreeIteratorType itVectorNS(nsReader->GetOutput()->GetDataTree());
  std::vector<double> accFirstOrderNS, accSecondOrderNS, minNS, maxNS;
  minNS.resize(descList.size());
  maxNS.resize(descList.size());
  accFirstOrderNS.resize(descList.size());
  accSecondOrderNS.resize(descList.size());
  std::fill(accFirstOrderNS.begin(), accFirstOrderNS.end(), 0);
  std::fill(accSecondOrderNS.begin(), accSecondOrderNS.end(), 0);
  std::fill(minNS.begin(), minNS.end(), 1);
  std::fill(maxNS.begin(), maxNS.end(), 0);
  unsigned int accNbElemNS = 0;

  for( itVectorNS.GoToBegin(); !itVectorNS.IsAtEnd(); ++itVectorNS )
    {
    if (!itVectorNS.Get()->IsRoot()
        && !itVectorNS.Get()->IsDocument()
        && !itVectorNS.Get()->IsFolder())
      {
      DataNodeType::Pointer currentGeometry = itVectorNS.Get();

      for (unsigned int i = 0; i < descList.size(); ++i)
        {
        double desc = currentGeometry->GetFieldAsDouble(descList[i]);

        accFirstOrderNS[i] += desc;
        accSecondOrderNS[i] += desc * desc;

        if (desc < minNS[i])
          {
          minNS[i] = desc;
          }
        if (desc > maxNS[i])
          {
          maxNS[i] = desc;
          }

        }
      accNbElemNS ++;
      }
    }
  std::cout << "Descriptors Stats : " << std::endl;
  std::cout << "Positive Samples" << std::endl;
  for (unsigned int i = 0; i < descList.size(); ++i)
    {
    double mean = accFirstOrderPS[i] / accNbElemPS;
    double stddev = vcl_sqrt( accSecondOrderPS[i]/accNbElemPS - mean*mean );
    std::cout << descList[i] << "  :  " << mean << " +/- " << stddev
        << "  (min: " << minPS[i] << "  max: " << maxPS[i] << ")"<< std::endl;
    }

  std::cout << "Negative Samples" << std::endl;
  for (unsigned int i = 0; i < descList.size(); ++i)
    {
    double mean = accFirstOrderNS[i] / accNbElemNS;
    double stddev = vcl_sqrt( accSecondOrderNS[i]/accNbElemNS - mean*mean );
    std::cout << descList[i] << "  :  " << mean << " +/- " << stddev
        << "  (min: " << minNS[i] << "  max: " << maxNS[i] << ")"<< std::endl;
    }

  OptimizerType::ParametersType
  initialPosition( 4 * descList.size() );

  if (parseResult->IsOptionPresent("InitModel"))
    {
    for(unsigned int i=0; i<4; i++)
      {
      for(unsigned int j=0; j< descList.size(); j++)
        {
        initialPosition.SetElement(i+4*j,   otb::FuzzyDescriptorsModelManager::GetDescriptor(descList[j].c_str(), descMod).second[i]);
        }
      }
    }
  else
    {
    for(unsigned int j=0; j< descList.size(); j++)
      {
      initialPosition.SetElement((j*4),   std::min(minNS[j], maxPS[j]));
      initialPosition.SetElement((j*4)+2, std::max(minNS[j], maxPS[j]));
      initialPosition.SetElement((j*4)+1, 0.5*(initialPosition.GetElement((j*4)) + initialPosition.GetElement((j*4)+2)));
      initialPosition.SetElement((j*4)+3, 0.95);
      }
    }

  //Cost Function
  //Format Hypothesis
  LabelSetType Bhyp, Phyp;
  int nbSet;

  nbSet = parseResult->GetNumberOfParameters("BeliefSupport");

  for (int i = 0; i < nbSet; i++)
    {
    std::string str = parseResult->GetParameterString("BeliefSupport", i);
    Bhyp.insert(str);
    }
  costFunction->SetBeliefHypothesis(Bhyp);
  nbSet = parseResult->GetNumberOfParameters("PlausibilitySupport");
  for (int i = 0; i < nbSet; i++)
    {
    std::string str = parseResult->GetParameterString("PlausibilitySupport", i);
    Phyp.insert(str);
    }
  costFunction->SetPlausibilityHypothesis(Phyp);

  if (parseResult->IsOptionPresent("Weighting"))
    {
    costFunction->SetWeight(parseResult->GetParameterDouble("Weighting"));
    }
  if (parseResult->IsOptionPresent("Criterion"))
    {
    costFunction->SetCriterionFormula(parseResult->GetParameterString("Criterion"));
    }

  costFunction->SetGTVectorData(psReader->GetOutput());
  costFunction->SetNSVectorData(nsReader->GetOutput());
  //Optimizer
  optimizer->SetCostFunction(costFunction);
  if (parseResult->IsOptionPresent("MaximumNumberOfIterations"))
    {
    optimizer->SetMaximumNumberOfIterations(parseResult->GetParameterInt("MaximumNumberOfIterations"));
    }
  else
    {
    optimizer->SetMaximumNumberOfIterations(200);
    }
  /*
  optimizer->SetParametersConvergenceTolerance( 0.01 );
  optimizer->SetFunctionConvergenceTolerance(0.001);
  */
  OptimizerType::ParametersType
  simplexDelta( costFunction->GetNumberOfParameters() );
  simplexDelta.Fill(0.1);

  optimizer->AutomaticInitialSimplexOff();
  optimizer->SetInitialSimplexDelta( simplexDelta );

  optimizer->SetInitialPosition(initialPosition);

  // Create the Command observer and register it with the optimizer.
  CommandIterationUpdate::Pointer observer = CommandIterationUpdate::New();
  if (parseResult->IsOptionPresent("OptimizerObserver"))
    {
    optimizer->AddObserver( itk::IterationEvent(), observer );
    }

  try
  {
    // do the optimization
    optimizer->StartOptimization();
  }
  catch( itk::ExceptionObject& err )
  {
    // An error has occurred in the optimization.
    // Update the parameters
    std::cout << "ERROR: Exception Catched!" << std::endl;
    std::cout << err.GetDescription() << std::endl;
    const unsigned int numberOfIterations
    = optimizer->GetOptimizer()->get_num_evaluations();
    std::cout << "numberOfIterations : " << numberOfIterations << std::endl;
    std::cout << "Results : " << optimizer->GetCurrentPosition() << std::endl;
  }
  // get the results
  const unsigned int numberOfIterations
  = optimizer->GetOptimizer()->get_num_evaluations();
  std::cout << "numberOfIterations : " << numberOfIterations << std::endl;
  std::cout << "Results : " << optimizer->GetCurrentPosition() << std::endl;

  otb::FuzzyDescriptorsModelManager::DescriptorsModelType model;

  for (unsigned int i=0; i < descList.size(); i++)
    {
    otb::FuzzyDescriptorsModelManager::ParameterType        tmpParams;
    for (unsigned int j = 0; j<4; j++)
      {
      tmpParams.push_back(optimizer->GetCurrentPosition()[(i*4)+j]);
      }
    otb::FuzzyDescriptorsModelManager::AddDescriptor(descList[i],
                                                     tmpParams,
                                                     model);
    }
  otb::FuzzyDescriptorsModelManager::Save(parseResult->GetParameterString("Output"),
                                          model);

  return EXIT_SUCCESS;
}
<commit_msg>ENH: port DSFuzzyModelEstimation to new Application framework.<commit_after>/*=========================================================================

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.

     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.

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

#include <iostream>

#include "otbWrapperApplication.h"
#include "otbWrapperApplicationFactory.h"
#include "otbWrapperStringListParameter.h"
#include "otbVectorData.h"
#include "otbImageToEnvelopeVectorDataFilter.h"
#include "otbVectorDataToRandomLineGenerator.h"
#include "itkAmoebaOptimizer.h"
#include "otbVectorDataToDSValidatedVectorDataFilter.h"
#include "otbStandardDSCostFunction.h"
#include "otbFuzzyDescriptorsModelManager.h"

namespace otb
{

namespace Wrapper
{

#include "itkCommand.h"
class CommandIterationUpdate : public itk::Command
{
public:
typedef  CommandIterationUpdate   Self;
typedef  itk::Command             Superclass;
typedef itk::SmartPointer<Self>   Pointer;
itkNewMacro( Self );
protected:
CommandIterationUpdate() {};
public:
typedef itk::AmoebaOptimizer         OptimizerType;
typedef   const OptimizerType   *    OptimizerPointer;

void Execute(itk::Object *caller, const itk::EventObject & event)
{
  Execute( (const itk::Object *)caller, event);
}

void Execute(const itk::Object * object, const itk::EventObject & event)
{
  OptimizerPointer optimizer =
      dynamic_cast< OptimizerPointer >( object );
  if( ! itk::IterationEvent().CheckEvent( &event ) )
    {
    return;
    }
  std::ostringstream message;
  message << optimizer->GetCachedValue() << "   ";
  message << optimizer->GetCachedCurrentPosition() << std::endl;
  std::cout<<message.str()<<std::endl;
}

};

class DSFuzzyModelEstimation: public Application
{
public:
  /** Standard class typedefs. */
  typedef DSFuzzyModelEstimation Self;
  typedef Application Superclass;
  typedef itk::SmartPointer<Self> Pointer;
  typedef itk::SmartPointer<const Self> ConstPointer;

  typedef VectorData<double>                          VectorDataType;

  typedef VectorDataType::DataTreeType                DataTreeType;
  typedef VectorDataType::DataNodeType                DataNodeType;

  typedef VectorDataType::ValuePrecisionType          PrecisionType;
  typedef VectorDataType::PrecisionType               CoordRepType;

  typedef otb::Wrapper::StringListParameter::StringListType         StringListType;

  typedef otb::VectorDataToDSValidatedVectorDataFilter<VectorDataType, PrecisionType>
                                                            ValidationFilterType;
  typedef otb::StandardDSCostFunction<ValidationFilterType> CostFunctionType;
  typedef CostFunctionType::LabelSetType                    LabelSetType;

  typedef itk::AmoebaOptimizer                            OptimizerType;

  typedef otb::FuzzyDescriptorsModelManager::DescriptorsModelType
                                                          DescriptorsModelType;
  typedef otb::FuzzyDescriptorsModelManager::DescriptorListType
                                                          DescriptorListType;

     typedef itk::PreOrderTreeIterator<VectorDataType::DataTreeType>
     TreeIteratorType;

  /** Standard macro */
  itkNewMacro(Self) ;

  itkTypeMacro(DSFuzzyModelEstimation, otb::Application) ;

private:

  DSFuzzyModelEstimation()
  {
    SetName("DSFuzzyModelEstimation");
    SetDescription("Estimate feature fuzzy model parameters using 2 vector data (ground truth samples and wrong samples).");

    SetDocName("Fuzzy Model estimation Application");
    SetDocLongDescription(" ");
    SetDocLimitations("");
    SetDocAuthors("OTB-Team");
    SetDocSeeAlso(" ");
    SetDocCLExample(
                    "otbApplicationLauncherCommandLine DSFuzzyModelEstimation  ${OTB-BIN}/bin  --psin ${OTB-Data}/Baseline/OTB-Applications/Files/cdbTvComputePolylineFeatureFromImage_LI_NOBUIL_gt.shp"
                    " --nsin ${OTB-Data}/Baseline/OTB-Applications/Files/cdbTvComputePolylineFeatureFromImage_LI_NOBUIL_wr.shp --belsup \"ROADSA\" --plasup \"NONDVI\" \"ROADSA\" \"NOBUIL\""
                    " --initmod ${OTB-Data}/Input/Dempster-Shafer/DSFuzzyModel_Init.xml --maxnbit 4 --optobs true"
                    "--out DSFuzzyModelEstimation.xml");

    AddDocTag(Tags::FeatureExtraction);
  }

  virtual ~DSFuzzyModelEstimation()
  {
  }

  void DoCreateParameters()
  {

    AddParameter(ParameterType_InputVectorData, "psin", "Input Positive Vector Data");
    SetParameterDescription("psin", "Ground truth vector data for positive samples");

    AddParameter(ParameterType_InputVectorData, "nsin", "Input Negative Vector Data");
    SetParameterDescription("nsin", "Ground truth vector data for negative samples");

    AddParameter(ParameterType_StringList, "belsup", "Belief Support");
    SetParameterDescription("belsup", "Dempster Shafer study hypothesis to compute belief");

    AddParameter(ParameterType_StringList, "plasup", "Plausibility Support");
    SetParameterDescription("plasup", "Dempster Shafer study hypothesis to compute plausibility");

    AddParameter(ParameterType_String, "cri", "Criterion");
    SetParameterDescription("cri", "Dempster Shafer criterion (by default (belief+plausibility)/2)");
    MandatoryOff("cri");
    SetParameterString("cri","((Belief + Plausibility)/2.)");

    AddParameter(ParameterType_Float,"wgt","Weighting");
    SetParameterDescription("wgt","Coefficient between 0 and 1 to promote undetection or false detections (default 0.5)");
    MandatoryOff("wgt");
    SetParameterFloat("wgt",0.5);

    AddParameter(ParameterType_Filename,"initmod","initial model");
    SetParameterDescription("initmod","Initial state for the model Optimizer");
    MandatoryOff("initmod");

    AddParameter(ParameterType_StringList, "desclist","Descriptor list");
    SetParameterDescription("desclist","List of the descriptors used in the model (must be specified to perform an automatic initialization)");
    MandatoryOff("desclist");
    SetParameterString("desclist","");

    AddParameter(ParameterType_Int,"maxnbit","Maximum number of iterations");
    MandatoryOff("maxnbit");
    SetParameterDescription("maxnbit","Maximum number of optimizer iteration (default 200)");
    SetParameterInt("maxnbit",200);

    AddParameter(ParameterType_Empty,"optobs","Optimizer Observer");
    SetParameterDescription("optobs","Activate the optimizer observer");
    MandatoryOff("optobs");

    AddParameter(ParameterType_Filename,"out","Output filename");
    SetParameterDescription("out","Output model file name (xml file)");
    SetParameterRole("out",Role_Output);

  }

  void DoUpdateParameters()
  {
    // Nothing to do here : all parameters are independent

    // .. //

  }

  void DoExecute()
  {

    //Instantiate
    m_CostFunction = CostFunctionType::New();
    m_Optimizer = OptimizerType::New();

    //Read the vector datas
    VectorDataType::Pointer psVectorData = GetParameterVectorData("psin");
    psVectorData->Update();
    VectorDataType::Pointer nsVectorData = GetParameterVectorData("psin");
    nsVectorData->Update();

    // Load the initial descriptor model
    DescriptorListType descList;
    DescriptorsModelType descMod;
    if (IsParameterEnabled("initmod"))
      {
      std::string descModFile = GetParameterString("initmod");
      descMod = FuzzyDescriptorsModelManager::Read(descModFile.c_str());
      descList = FuzzyDescriptorsModelManager::GetDescriptorList(descMod);
      }
    else
      {
      StringListType stringList = GetParameterStringList("desclist");
      int nbsdDesc = stringList.size();
      for (int i = 0; i < nbsdDesc; i++)
        {
        descList.push_back(stringList[i]);
        }
      }

    m_CostFunction->SetDescriptorList(descList);

    // Compute statistics of all the descriptors

    std::vector<double> accFirstOrderPS, accSecondOrderPS, minPS, maxPS;
    accFirstOrderPS.resize(descList.size());
    accSecondOrderPS.resize(descList.size());
    std::fill(accFirstOrderPS.begin(), accFirstOrderPS.end(), 0);
    std::fill(accSecondOrderPS.begin(), accSecondOrderPS.end(), 0);
    minPS.resize(descList.size());
    maxPS.resize(descList.size());
    unsigned int accNbElemPS = 0;

    TreeIteratorType itVectorPS(psVectorData->GetDataTree());
    for (itVectorPS.GoToBegin(); !itVectorPS.IsAtEnd(); ++itVectorPS)
      {
      if (!itVectorPS.Get()->IsRoot() && !itVectorPS.Get()->IsDocument() && !itVectorPS.Get()->IsFolder())
        {
        DataNodeType::Pointer currentGeometry = itVectorPS.Get();

        for (unsigned int i = 0; i < descList.size(); ++i)
          {
          double desc = currentGeometry->GetFieldAsDouble(descList[i]);

          accFirstOrderPS[i] += desc;
          accSecondOrderPS[i] += desc * desc;

          if (desc < minPS[i])
            {
            minPS[i] = desc;
            }
          if (desc > maxPS[i])
            {
            maxPS[i] = desc;
            }

          }
        accNbElemPS++;
        }
      }

    TreeIteratorType itVectorNS(nsVectorData->GetDataTree());
    std::vector<double> accFirstOrderNS, accSecondOrderNS, minNS, maxNS;
    minNS.resize(descList.size());
    maxNS.resize(descList.size());
    accFirstOrderNS.resize(descList.size());
    accSecondOrderNS.resize(descList.size());
    std::fill(accFirstOrderNS.begin(), accFirstOrderNS.end(), 0);
    std::fill(accSecondOrderNS.begin(), accSecondOrderNS.end(), 0);
    std::fill(minNS.begin(), minNS.end(), 1);
    std::fill(maxNS.begin(), maxNS.end(), 0);
    unsigned int accNbElemNS = 0;

    for (itVectorNS.GoToBegin(); !itVectorNS.IsAtEnd(); ++itVectorNS)
      {
      if (!itVectorNS.Get()->IsRoot() && !itVectorNS.Get()->IsDocument() && !itVectorNS.Get()->IsFolder())
        {
        DataNodeType::Pointer currentGeometry = itVectorNS.Get();

        for (unsigned int i = 0; i < descList.size(); ++i)
          {
          double desc = currentGeometry->GetFieldAsDouble(descList[i]);

          accFirstOrderNS[i] += desc;
          accSecondOrderNS[i] += desc * desc;

          if (desc < minNS[i])
            {
            minNS[i] = desc;
            }
          if (desc > maxNS[i])
            {
            maxNS[i] = desc;
            }

          }
        accNbElemNS++;
        }
      }
    otbAppLogINFO( << "Descriptors Stats : ");
    otbAppLogINFO( << "Positive Samples");
    for (unsigned int i = 0; i < descList.size(); ++i)
      {
      double mean = accFirstOrderPS[i] / accNbElemPS;
      double stddev = vcl_sqrt(accSecondOrderPS[i] / accNbElemPS - mean * mean);
      otbAppLogINFO( << descList[i] << "  :  " << mean << " +/- " << stddev << "  (min: " << minPS[i] << "  max: " << maxPS[i] << ")"<< std::endl);
      }

    otbAppLogINFO( << "Negative Samples" << std::endl);
    for (unsigned int i = 0; i < descList.size(); ++i)
      {
      double mean = accFirstOrderNS[i] / accNbElemNS;
      double stddev = vcl_sqrt(accSecondOrderNS[i] / accNbElemNS - mean * mean);
      otbAppLogINFO(<< descList[i] << "  :  " << mean << " +/- " << stddev << "  (min: " << minNS[i] << "  max: " << maxNS[i] << ")"<< std::endl);
      }

    OptimizerType::ParametersType initialPosition(4 * descList.size());

    if (IsParameterEnabled("initmod"))
      {

      for (unsigned int i = 0; i < 4; i++)
        {
        for (unsigned int j = 0; j < descList.size(); j++)
          {
          initialPosition.SetElement(
                                     i + 4 * j,
                                     otb::FuzzyDescriptorsModelManager::GetDescriptor(descList[j].c_str(), descMod).second[i]);
          }
        }
      }
    else
      {
      for (unsigned int j = 0; j < descList.size(); j++)
        {
        initialPosition.SetElement((j * 4), std::min(minNS[j], maxPS[j]));
        initialPosition.SetElement((j * 4) + 2, std::max(minNS[j], maxPS[j]));
        initialPosition.SetElement(
                                   (j * 4) + 1,
                                       0.5
                                       * (initialPosition.GetElement((j * 4)) + initialPosition.GetElement((j * 4) + 2)));
        initialPosition.SetElement((j * 4) + 3, 0.95);
        }
      }

    //Cost Function
    //Format Hypothesis
    LabelSetType Bhyp, Phyp;
    int nbSet;

    StringListType stringList = GetParameterStringList("belsup");
    nbSet = stringList.size();

    for (int i = 0; i < nbSet; i++)
      {
      std::string str = stringList[i];
      Bhyp.insert(str);
      }
    m_CostFunction->SetBeliefHypothesis(Bhyp);
    stringList = GetParameterStringList("plasup");
    nbSet = stringList.size();
    for (int i = 0; i < nbSet; i++)
      {
      std::string str = stringList[i];
      Phyp.insert(str);
      }
    m_CostFunction->SetPlausibilityHypothesis(Phyp);

    m_CostFunction->SetWeight(GetParameterFloat("wgt"));

    m_CostFunction->SetCriterionFormula(GetParameterString("cri"));

    m_CostFunction->SetGTVectorData(psVectorData);
    m_CostFunction->SetNSVectorData(nsVectorData);
    //Optimizer
    m_Optimizer->SetCostFunction(m_CostFunction);

    m_Optimizer->SetMaximumNumberOfIterations(GetParameterInt("maxnbit"));

    OptimizerType::ParametersType simplexDelta(m_CostFunction->GetNumberOfParameters());
    simplexDelta.Fill(0.1);

    m_Optimizer->AutomaticInitialSimplexOff();
    m_Optimizer->SetInitialSimplexDelta(simplexDelta);

    m_Optimizer->SetInitialPosition(initialPosition);

    // Create the Command observer and register it with the optimizer.
    CommandIterationUpdate::Pointer observer = CommandIterationUpdate::New();
    if (IsParameterEnabled("optobs"))
      {
      m_Optimizer->AddObserver(itk::IterationEvent(), observer);
      }

    try
      {
      // do the optimization
      m_Optimizer->StartOptimization();
      }
    catch (itk::ExceptionObject& err)
      {
      // An error has occurred in the optimization.
      // Update the parameters
      otbAppLogFATAL("ERROR: Exception Catched!" << std::endl);
      otbAppLogFATAL(<< err.GetDescription() << std::endl);
      const unsigned int numberOfIterations = m_Optimizer->GetOptimizer()->get_num_evaluations();
      otbAppLogFATAL("numberOfIterations : " << numberOfIterations << std::endl);
      otbAppLogFATAL("Results : " << m_Optimizer->GetCurrentPosition() << std::endl);
      }
    // get the results
    const unsigned int numberOfIterations = m_Optimizer->GetOptimizer()->get_num_evaluations();
    otbAppLogFATAL("numberOfIterations : " << numberOfIterations << std::endl);
    otbAppLogFATAL("Results : " << m_Optimizer->GetCurrentPosition() << std::endl);

    for (unsigned int i = 0; i < descList.size(); i++)
      {
      otb::FuzzyDescriptorsModelManager::ParameterType tmpParams;
      for (unsigned int j = 0; j < 4; j++)
        {
        tmpParams.push_back(m_Optimizer->GetCurrentPosition()[(i * 4) + j]);
        }
      otb::FuzzyDescriptorsModelManager::AddDescriptor(descList[i], tmpParams, m_Model);
      }
    otb::FuzzyDescriptorsModelManager::Save(GetParameterString("out"), m_Model);

  };

  CostFunctionType::Pointer                               m_CostFunction;
  OptimizerType::Pointer                                  m_Optimizer;
  otb::FuzzyDescriptorsModelManager::DescriptorsModelType m_Model;
};

}
}

OTB_APPLICATION_EXPORT(otb::Wrapper::DSFuzzyModelEstimation)

<|endoftext|>


<commit_before>/*******************************************************
 Windows HID simplification

 Alan Ott
 Signal 11 Software

 8/22/2009

 Copyright 2009, All Rights Reserved.

 This contents of this file may be used by anyone
 for any reason without any conditions and may be
 used as a starting point for your own applications
 which use HIDAPI.

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

#include <stdio.h>
#include <wchar.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <signal.h>
#include <time.h>
#include <assert.h>

enum {
    HID_ERROR               = -1,
    VENDOR_ID               = 0x06A3,
    RP_PROD_ID              = 0x0D05,
    MP_PROD_ID              = 0x0D06,
    SP_PROD_ID              = 0x0D07,
    RP_ERROR_THRESH         = 40,
    MP_ERROR_THRESH         = 40,
    SP_ERROR_THRESH         = 40,
    PANEL_CHECK_INTERVAL    = 5 // seconds
};

// Headers needed for sleeping.
#ifdef _WIN32
	#include <windows.h>
#else
	#include <unistd.h>
#endif

#include "hidapi.h"

hid_device *handle;

void signal_handler(int32_t signal)
{
    struct tm*  ptr = 0;
    time_t      tm  = time(0);

    ptr             = localtime(&tm);

    switch(signal)
    {
        case SIGFPE:
            perror("---------------- \n");
            perror(asctime(ptr));
            perror("A floating point exception occured.\n");
            break;
        case SIGILL:
            perror("---------------- \n");
            perror(asctime(ptr));
            perror("An illegal instruction occured.\n");
            break;
        case SIGINT:
            // the user hit CTRL-C
//            perror("\n");
printf("closing \n");
            break;
        case SIGSEGV:
            perror("---------------- \n");
            perror(asctime(ptr));
            perror("A segmentation violation occured.\n");
            break;
        default:
            perror("---------------- \n");
            perror(asctime(ptr));
            perror("An unknown signal was caught.\n");
            break;
    }

    if (handle)
        hid_close(handle);

    // pass a successful exit so our atexit handler is called
    exit(EXIT_SUCCESS);
}

int main(int argc, char* argv[])
{
	int res;
    unsigned int cnt = 0;
	unsigned char buf[256];
	unsigned char buf2[4];
	#define MAX_STR 255
	wchar_t wstr[MAX_STR];

	int i;

#ifdef WIN32
	UNREFERENCED_PARAMETER(argc);
	UNREFERENCED_PARAMETER(argv);
#endif

	struct hid_device_info *devs, *cur_dev;

    // siganl handlers
    if(signal(SIGFPE, signal_handler) == SIG_ERR)
        perror("An error occured while setting the SIGFPE signal handler.\n");

    if(signal(SIGILL, signal_handler) == SIG_ERR)
        perror("An error occured while setting the SIGILL signal handler.\n");

    if(signal(SIGINT, signal_handler) == SIG_ERR)
        perror("An error occured while setting the SIGINT signal handler.\n");

    if(signal(SIGSEGV, signal_handler) == SIG_ERR)
        perror("An error occured while setting the SIGSEGV signal handler.\n");

//	devs = hid_enumerate(0x0, 0x0);
//	cur_dev = devs;
//	while (cur_dev) {
//		printf("Device Found\n  type: %04hx %04hx\n  path: %s\n  serial_number: %ls", cur_dev->vendor_id, cur_dev->product_id, cur_dev->path, cur_dev->serial_number);
//		printf("\n");
//		printf("  Manufacturer: %ls\n", cur_dev->manufacturer_string);
//		printf("  Product:      %ls\n", cur_dev->product_string);
//		printf("\n");
//		cur_dev = cur_dev->next;
//	}
//	hid_free_enumeration(devs);

	// Set up the command buffer.
	memset(buf,0x00,sizeof(buf));
//	buf[0] = 0x01;
//	buf[1] = 0x81;

	// Open the device using the VID, PID,
	// and optionally the Serial number.
	////handle = hid_open(0x4d8, 0x3f, L"12345");
//	handle = hid_open(0x4d8, 0x3f, NULL);

// saitek pro control panels
	handle = hid_open(NULL, VENDOR_ID, MP_PROD_ID, NULL);
	if (!handle) {
		printf("unable to open device\n");
 		return 1;
	}

	// Read the Manufacturer String
	wstr[0] = 0x0000;
	res = hid_get_manufacturer_string(handle, wstr, MAX_STR);
	if (res < 0)
		printf("Unable to read manufacturer string\n");
	printf("Manufacturer String: %ls\n", wstr);

	// Read the Product String
	wstr[0] = 0x0000;
	res = hid_get_product_string(handle, wstr, MAX_STR);
	if (res < 0)
		printf("Unable to read product string\n");
	printf("Product String: %ls\n", wstr);

	// Read the Serial Number String
	wstr[0] = 0x0000;
	res = hid_get_serial_number_string(handle, wstr, MAX_STR);
	if (res < 0)
		printf("Unable to read serial number string\n");
	printf("Serial Number String: (%d) %ls", wstr[0], wstr);
	printf("\n");

	// Read Indexed String 1
	wstr[0] = 0x0000;
	res = hid_get_indexed_string(handle, 1, wstr, MAX_STR);
	if (res < 0)
		printf("Unable to read indexed string 1\n");
	printf("Indexed String 1: %ls\n", wstr);

	// Set the hid_read() function to be non-blocking.
//	hid_set_nonblocking(handle, 1);

	// Try to read from the device. There shoud be no
	// data here, but execution should not block.
//	res = hid_read(handle, buf, 4);

	// Send a Feature Report to the device
//	memset(buf,0x09,sizeof(buf));
//	buf[12] = 0x01;
//	buf[11] = 0x01;
//	buf[10] = 0x10;
//	buf[0] = 0x2;
//	buf[1] = 0xa0;
//	buf[2] = 0x0a;
//	buf[3] = 0x00;
//	buf[4] = 0x00;
//	res = hid_send_feature_report(handle, buf, 13);
//	if (res < 0) {
//		printf("Unable to send a feature report.\n");
//	}

//	buf[12] = 0x00;
//	buf[11] = 0x80;
//	buf[10] = 0x10;
//	res = hid_write(handle, buf, 13);
//	if (res < 0) {
//		printf("Unable to write()\n");
//		printf("Error: %ls\n", hid_error(handle));
//	}

//    memset(buf,0x00,sizeof(buf));
//                buf[12] = 0x00;

    memset(buf,0x00,sizeof(buf));
//    buf[0] = 0;
//    buf[1] = 1;
//    buf[13] = 0;
//hid_send_feature_report(handle, buf, 13);
//return 1;
    while (1) {
        if (hid_check(VENDOR_ID, MP_PROD_ID)) {
            if (handle) {
                buf[11] = 0x00;
                hid_send_feature_report(handle, buf, 13);
                printf("sleep: %d\n", cnt++);
                sleep(1);
                buf[11] = 0x01;
                hid_send_feature_report(handle, buf, 13);
                sleep(1);

                continue;
            }
        } else {
            printf("no hid\n");
        }
        if (handle) {
            hid_close(handle);
 printf("hid closed\n");
            handle = NULL;
        }
        handle = hid_open(NULL, VENDOR_ID, MP_PROD_ID, NULL);
        if (!handle) {
            printf("unable to open device\n");
        } else {
            printf("device open\n");
        }

        sleep(1);
    }

	// Read the Manufacturer String
//	wstr[0] = 0x0000;
//	res = hid_get_manufacturer_string(handle, wstr, MAX_STR);
//	if (res < 0)
//		printf("Unable to read manufacturer string\n");
//    }

//	res = 0;
//	while (1) {
//		res = hid_read(handle, buf2, sizeof(buf2));
//		if (res == 0)
//			printf("waiting...\n");
//		else if (res < 0)
//			printf("Unable to read()\n");
//        else {
//            for (i = 0; i < res; i++)
//                printf("%02hhx ", buf2[i]);
//            printf("\n");
//            memset(buf2,0x00,sizeof(buf2));
//        }
//		#ifdef WIN32
//		Sleep(500);
//		#else
//		usleep(500*1000);
//		#endif
//	}
#if 0
	memset(buf,0,sizeof(buf));

	// Read a Feature Report from the device
	buf[0] = 0x2;
	res = hid_get_feature_report(handle, buf, sizeof(buf));
	if (res < 0) {
		printf("Unable to get a feature report.\n");
		printf("%ls", hid_error(handle));
	}
	else {
		// Print out the returned buffer.
		printf("Feature Report\n   ");
		for (i = 0; i < res; i++)
			printf("%02hhx ", buf[i]);
		printf("\n");
	}

	memset(buf,0,sizeof(buf));

	// Toggle LED (cmd 0x80). The first byte is the report number (0x1).
	buf[0] = 0x00;
	buf[1] = 0x81;
	buf[2] = 0x10;
	res = hid_write(handle, buf, 13);
	if (res < 0) {
		printf("Unable to write()\n");
		printf("Error: %ls\n", hid_error(handle));
	}

	// Request state (cmd 0x81). The first byte is the report number (0x1).
	buf[0] = 0x1;
	buf[1] = 0x81;
	hid_write(handle, buf, 13);
	if (res < 0)
		printf("Unable to write() (2)\n");

	// Read requested state. hid_read() has been set to be
	// non-blocking by the call to hid_set_nonblocking() above.
	// This loop demonstrates the non-blocking nature of hid_read().
	res = 0;
	while (res == 0) {
		res = hid_read(handle, buf, sizeof(buf));
		if (res == 0)
			printf("waiting...\n");
		if (res < 0)
			printf("Unable to read()\n");
		#ifdef WIN32
		Sleep(500);
		#else
		usleep(500*1000);
		#endif
	}

	printf("Data read:\n   ");
	// Print out the returned buffer.
	for (i = 0; i < res; i++)
		printf("%02hhx ", buf[i]);
	printf("\n");
#endif

#ifdef WIN32
	system("pause");
#endif

	return 1;
}
<commit_msg>removed hid test file<commit_after><|endoftext|>


<commit_before>// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s

// Make sure we handle contexts correctly with sizeof
template<typename T> void f(T n) {
  int buffer[n];
  [] { int x = sizeof(sizeof(buffer)); }();
}
int main() {
  f<int>(1);
}

// Make sure we handle references to non-static data members in unevaluated
// contexts in class template methods correctly. Previously we assumed these
// would be valid MemberRefExprs, but they have no 'this' so we need to form a
// DeclRefExpr to the FieldDecl instead.
// PR26893
template <class T>
struct M {
  M() {}; // expected-note {{in instantiation of default member initializer 'M<S>::m' requested here}}
  int m = *T::x; // expected-error {{invalid use of non-static data member 'x'}}
  void f() {
    // These are valid.
    static_assert(sizeof(T::x) == 8, "ptr");
    static_assert(sizeof(*T::x) == 4, "int");
  }
};
struct S { int *x; };
template struct M<S>; // expected-note {{in instantiation of member function 'M<S>::M' requested here}}

// Similar test case for PR26893.
template <typename T=void>
struct bar {
  struct foo { int array[10]; };
  int baz() { return sizeof(foo::array); }
};
template struct bar<>;
<commit_msg>Add missing triple to instantiate-sizeof.cpp test<commit_after>// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsyntax-only -verify -std=c++11 %s

// Make sure we handle contexts correctly with sizeof
template<typename T> void f(T n) {
  int buffer[n];
  [] { int x = sizeof(sizeof(buffer)); }();
}
int main() {
  f<int>(1);
}

// Make sure we handle references to non-static data members in unevaluated
// contexts in class template methods correctly. Previously we assumed these
// would be valid MemberRefExprs, but they have no 'this' so we need to form a
// DeclRefExpr to the FieldDecl instead.
// PR26893
template <class T>
struct M {
  M() {}; // expected-note {{in instantiation of default member initializer 'M<S>::m' requested here}}
  int m = *T::x; // expected-error {{invalid use of non-static data member 'x'}}
  void f() {
    // These are valid.
    static_assert(sizeof(T::x) == 8, "ptr");
    static_assert(sizeof(*T::x) == 4, "int");
  }
};
struct S { int *x; };
template struct M<S>; // expected-note {{in instantiation of member function 'M<S>::M' requested here}}

// Similar test case for PR26893.
template <typename T=void>
struct bar {
  struct foo { int array[10]; };
  int baz() { return sizeof(foo::array); }
};
template struct bar<>;
<|endoftext|>


<commit_before>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2014.  All rights reserved
 */
#include    "../../StroikaPreComp.h"

#include    <cstdarg>
#include    <iomanip>
#include    <sstream>

#include    "../../Math/Common.h"
#include    "../../Memory/SmallStackBuffer.h"
#include    "../CodePage.h"

#include    "Utilities.h"

using   namespace   Stroika;
using   namespace   Stroika::Foundation;
using   namespace   Stroika::Foundation::Characters;
using   namespace   Stroika::Foundation::Characters::CString;

/*
 ********************************************************************************
 ************************************* Format ***********************************
 ********************************************************************************
 */
string  Characters::CString::FormatV (const char* format, va_list argsList)
{
    RequireNotNull (format);
    Memory::SmallStackBuffer<char, 10 * 1024> msgBuf (10 * 1024);
#if     qSupportValgrindQuirks
    // Makes little sense - even msgBuf[0] not sufficient - but this silences lots of warnings.
    // -- LGP 2012-05-19
    memset (msgBuf, 0, sizeof (msgBuf[0]) * msgBuf.GetSize());
#endif
#if     __STDC_WANT_SECURE_LIB__
    while (::vsnprintf_s (msgBuf, msgBuf.GetSize (), msgBuf.GetSize () - 1, format, argsList) < 0) {
        msgBuf.GrowToSize (msgBuf.GetSize () * 2);
    }
#else
    // SUBTLE: va_list looks like it is passed by value, but its not really,
    // and vswprintf, at least on GCC munges it. So we must use va_copy() to do this safely
    // @see http://en.cppreference.com/w/cpp/utility/variadic/va_copy
    va_list argListCopy ;
    va_copy(argListCopy, argsList);

    while (::vsnprintf (msgBuf, msgBuf.GetSize (), format, argsList) < 0) {
        msgBuf.GrowToSize (msgBuf.GetSize () * 2);
        va_end (argListCopy);
        va_copy (argListCopy, argsList);
    }

    va_end (argListCopy);
#endif
    Assert (::strlen (msgBuf) < msgBuf.GetSize ());
    return string (msgBuf);
}

string  Characters::CString::Format (const char* format, ...)
{
    va_list     argsList;
    va_start (argsList, format);
    string  tmp = FormatV (format, argsList);
    va_end (argsList);
    return tmp;
}

DISABLE_COMPILER_MSC_WARNING_START(6262)
wstring Characters::CString::FormatV (const wchar_t* format, va_list argsList)
{
    RequireNotNull (format);
    Memory::SmallStackBuffer<wchar_t, 10 * 1024>  msgBuf (10 * 1024);
    const   wchar_t*    useFormat   =   format;
#if     !qStdLibSprintfAssumesPctSIsWideInFormatIfWideFormat
    wchar_t     newFormat[5 * 1024];
    {
        size_t  origFormatLen   =   wcslen (format);
        Require (origFormatLen < NEltsOf (newFormat) / 2);  // just to be sure safe - this is already crazy-big for format string...
        // Could use Memory::SmallStackBuffer<> but I doubt this will ever get triggered
        bool lookingAtFmtCvt = false;
        size_t  newFormatIdx    =   0;
        for (size_t i = 0; i < origFormatLen; ++i) {
            if (lookingAtFmtCvt) {
                switch (format[i]) {
                    case    '%': {
                            lookingAtFmtCvt = false;
                        }
                        break;
                    case    's': {
                            newFormat[newFormatIdx] = 'l';
                            newFormatIdx++;
                        }
                        break;
                    case    '.': {
                            // could still be part for format string
                        }
                        break;
                    default: {
                            if (isdigit (format[i])) {
                                // could still be part for format string
                            }
                            else {
                                lookingAtFmtCvt = false;    // DONE
                            }
                        }
                        break;
                }
            }
            else {
                if (format[i] == '%') {
                    lookingAtFmtCvt = true;
                }
            }
            newFormat[newFormatIdx] = format[i];
            newFormatIdx++;
        }
        Assert (newFormatIdx >= origFormatLen);
        if (newFormatIdx > origFormatLen) {
            newFormat[newFormatIdx] = '\0';
            useFormat   =   newFormat;
        }
    }
#endif

#if     qSupportValgrindQuirks
    // Makes little sense - even msgBuf[0] not sufficient - but this silences lots of warnings.
    // -- LGP 2012-05-19
    memset (msgBuf, 0, sizeof (msgBuf[0]) * msgBuf.GetSize());
#endif

    // SUBTLE: va_list looks like it is passed by value, but its not really,
    // and vswprintf, at least on GCC munges it. So we must use va_copy() to do this safely
    // @see http://en.cppreference.com/w/cpp/utility/variadic/va_copy
    va_list argListCopy ;
    va_copy(argListCopy, argsList);

    // Assume only reason for failure is not enuf bytes, so allocate more.
    // If I'm wrong, we'll just runout of memory and throw out...
    while (::vswprintf (msgBuf, msgBuf.GetSize (), useFormat, argsList) < 0) {
        msgBuf.GrowToSize (msgBuf.GetSize () * 2);
        va_end (argListCopy);
        va_copy (argListCopy, argsList);
    }
    va_end (argListCopy);
    Assert (::wcslen (msgBuf) < msgBuf.GetSize ());
    return wstring (msgBuf);
}
DISABLE_COMPILER_MSC_WARNING_END(6262)

wstring Characters::CString::Format (const wchar_t* format, ...)
{
    va_list     argsList;
    va_start (argsList, format);
    wstring tmp = FormatV (format, argsList);
    va_end (argsList);
    return tmp;
}

/*
 ********************************************************************************
 ********************************* LimitLength **********************************
 ********************************************************************************
 */
namespace   {
    template    <typename STRING>
    inline  STRING  LimitLength_HLPR (const STRING& str, size_t maxLen, bool keepLeft, const STRING& kELIPSIS)
    {
        if (str.length () <= maxLen) {
            return str;
        }
        size_t  useLen  =   maxLen;
        if (useLen > kELIPSIS.length ()) {
            useLen -= kELIPSIS.length ();
        }
        else {
            useLen = 0;
        }
        if (keepLeft) {
            return str.substr (0, useLen) + kELIPSIS;
        }
        else {
            return kELIPSIS + str.substr (str.length () - useLen);
        }
    }
}
string  Characters::CString::LimitLength (const string& str, size_t maxLen, bool keepLeft)
{
    return LimitLength_HLPR<string> (str, maxLen, keepLeft, "...");
}

wstring Characters::CString::LimitLength (const wstring& str, size_t maxLen, bool keepLeft)
{
    return LimitLength_HLPR<wstring> (str, maxLen, keepLeft, L"...");
}

/*
 ********************************************************************************
 *************************** StripTrailingCharIfAny *****************************
 ********************************************************************************
 */
namespace   {
    template    <typename STRING>
    inline  STRING  StripTrailingCharIfAny_HLPR (const STRING& str, typename STRING::value_type c)
    {
        if (str.size () > 0 and str[str.size () - 1] == c) {
            STRING  tmp =   str;
            tmp.erase (tmp.size () - 1);
            return tmp;
        }
        return str;
    }
}

string  Characters::CString::StripTrailingCharIfAny (const string& s, char c)
{
    return StripTrailingCharIfAny_HLPR (s, c);
}

wstring Characters::CString::StripTrailingCharIfAny (const wstring& s, wchar_t c)
{
    return StripTrailingCharIfAny_HLPR (s, c);
}

/*
 ********************************************************************************
 ********************************* Float2String *********************************
 ********************************************************************************
 */
wstring Characters::CString::Float2String (double f)
{
    if (std::isnan (f)) {
        return wstring ();
    }
    wstringstream s;
    s.imbue (locale ("C"));
    s << f;
    return s.str ();
}

/*
 ********************************************************************************
 ****************************** HexString2Int ***********************************
 ********************************************************************************
 */
unsigned int Characters::CString::HexString2Int (const string& s)
{
    using   std::numeric_limits;
    unsigned    long    l   =   strtoul (s.c_str (), nullptr, 16);
    if (l >= numeric_limits<unsigned int>::max ()) {
        return numeric_limits<unsigned int>::max ();
    }
    return l;
}

unsigned int Characters::CString::HexString2Int (const wchar_t* s)
{
    using   std::numeric_limits;
    RequireNotNull (s);
    unsigned    long    l   =   wcstoul (s, nullptr, 16);
    if (l >= numeric_limits<unsigned int>::max ()) {
        return numeric_limits<unsigned int>::max ();
    }
    return l;
}

unsigned int Characters::CString::HexString2Int (const wstring& s)
{
    using   std::numeric_limits;
    unsigned    long    l   =   wcstoul (s.c_str (), nullptr, 16);
    if (l >= numeric_limits<unsigned int>::max ()) {
        return numeric_limits<unsigned int>::max ();
    }
    return l;
}

/*
 ********************************************************************************
 ********************************* String2Int ***********************************
 ********************************************************************************
 */
long long int Characters::CString::Private_::String2Int_ (const string& s)
{
    using   std::numeric_limits;
    // nothing needed todo to pin the value to min/max
    return strtoll (s.c_str (), nullptr, 10);
}

long long int Characters::CString::Private_::String2Int_ (const wstring& s)
{
    using   std::numeric_limits;
    unsigned    long long int    l   =   wcstoll (s.c_str (), nullptr, 10);
    return l;
}

/*
 ********************************************************************************
 ********************************* String2UInt ***********************************
 ********************************************************************************
 */
unsigned long long int Characters::CString::Private_::String2UInt_ (const string& s)
{
    using   std::numeric_limits;
    // nothing needed todo to pin the value to min/max
    unsigned    long long int    l = strtoull (s.c_str (), nullptr, 10);
    return l;
}

unsigned long long int Characters::CString::Private_::String2UInt_ (const wstring& s)
{
    using   std::numeric_limits;
    long long int    l   =   wcstoull (s.c_str (), nullptr, 10);
    return l;
}

/*
 ********************************************************************************
 ********************************* String2Float *********************************
 ********************************************************************************
 */
double  Characters::CString::String2Float (const string& s)
{
    char*   e   =   nullptr;
    double  d   =   strtod (s.c_str (), &e);
    if (d == 0) {
        if (s.c_str () == e) {
            return Math::nan<double> ();
        }
    }
    return d;
}

double  Characters::CString::String2Float (const wchar_t* s)
{
    RequireNotNull (s);
    wchar_t*    e   =   nullptr;
    double  d   =   wcstod (s, &e);
    if (d == 0) {
        if (s == e) {
            return Math::nan<double> ();
        }
    }
    return d;
}

double  Characters::CString::String2Float (const wstring& s)
{
    wchar_t*    e   =   nullptr;
    double  d   =   wcstod (s.c_str (), &e);
    if (d == 0) {
        if (s.c_str () == e) {
            return Math::nan<double> ();
        }
    }
    return d;
}
<commit_msg>small error in last checkin/fix<commit_after>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2014.  All rights reserved
 */
#include    "../../StroikaPreComp.h"

#include    <cstdarg>
#include    <iomanip>
#include    <sstream>

#include    "../../Math/Common.h"
#include    "../../Memory/SmallStackBuffer.h"
#include    "../CodePage.h"

#include    "Utilities.h"

using   namespace   Stroika;
using   namespace   Stroika::Foundation;
using   namespace   Stroika::Foundation::Characters;
using   namespace   Stroika::Foundation::Characters::CString;

/*
 ********************************************************************************
 ************************************* Format ***********************************
 ********************************************************************************
 */
string  Characters::CString::FormatV (const char* format, va_list argsList)
{
    RequireNotNull (format);
    Memory::SmallStackBuffer<char, 10 * 1024> msgBuf (10 * 1024);
#if     qSupportValgrindQuirks
    // Makes little sense - even msgBuf[0] not sufficient - but this silences lots of warnings.
    // -- LGP 2012-05-19
    memset (msgBuf, 0, sizeof (msgBuf[0]) * msgBuf.GetSize());
#endif
#if     __STDC_WANT_SECURE_LIB__
    while (::vsnprintf_s (msgBuf, msgBuf.GetSize (), msgBuf.GetSize () - 1, format, argsList) < 0) {
        msgBuf.GrowToSize (msgBuf.GetSize () * 2);
    }
#else
    // SUBTLE: va_list looks like it is passed by value, but its not really,
    // and vswprintf, at least on GCC munges it. So we must use va_copy() to do this safely
    // @see http://en.cppreference.com/w/cpp/utility/variadic/va_copy
    va_list argListCopy ;
    va_copy(argListCopy, argsList);

    while (::vsnprintf (msgBuf, msgBuf.GetSize (), format, argListCopy) < 0) {
        msgBuf.GrowToSize (msgBuf.GetSize () * 2);
        va_end (argListCopy);
        va_copy (argListCopy, argsList);
    }

    va_end (argListCopy);
#endif
    Assert (::strlen (msgBuf) < msgBuf.GetSize ());
    return string (msgBuf);
}

string  Characters::CString::Format (const char* format, ...)
{
    va_list     argsList;
    va_start (argsList, format);
    string  tmp = FormatV (format, argsList);
    va_end (argsList);
    return tmp;
}

DISABLE_COMPILER_MSC_WARNING_START(6262)
wstring Characters::CString::FormatV (const wchar_t* format, va_list argsList)
{
    RequireNotNull (format);
    Memory::SmallStackBuffer<wchar_t, 10 * 1024>  msgBuf (10 * 1024);
    const   wchar_t*    useFormat   =   format;
#if     !qStdLibSprintfAssumesPctSIsWideInFormatIfWideFormat
    wchar_t     newFormat[5 * 1024];
    {
        size_t  origFormatLen   =   wcslen (format);
        Require (origFormatLen < NEltsOf (newFormat) / 2);  // just to be sure safe - this is already crazy-big for format string...
        // Could use Memory::SmallStackBuffer<> but I doubt this will ever get triggered
        bool lookingAtFmtCvt = false;
        size_t  newFormatIdx    =   0;
        for (size_t i = 0; i < origFormatLen; ++i) {
            if (lookingAtFmtCvt) {
                switch (format[i]) {
                    case    '%': {
                            lookingAtFmtCvt = false;
                        }
                        break;
                    case    's': {
                            newFormat[newFormatIdx] = 'l';
                            newFormatIdx++;
                        }
                        break;
                    case    '.': {
                            // could still be part for format string
                        }
                        break;
                    default: {
                            if (isdigit (format[i])) {
                                // could still be part for format string
                            }
                            else {
                                lookingAtFmtCvt = false;    // DONE
                            }
                        }
                        break;
                }
            }
            else {
                if (format[i] == '%') {
                    lookingAtFmtCvt = true;
                }
            }
            newFormat[newFormatIdx] = format[i];
            newFormatIdx++;
        }
        Assert (newFormatIdx >= origFormatLen);
        if (newFormatIdx > origFormatLen) {
            newFormat[newFormatIdx] = '\0';
            useFormat   =   newFormat;
        }
    }
#endif

#if     qSupportValgrindQuirks
    // Makes little sense - even msgBuf[0] not sufficient - but this silences lots of warnings.
    // -- LGP 2012-05-19
    memset (msgBuf, 0, sizeof (msgBuf[0]) * msgBuf.GetSize());
#endif

    // SUBTLE: va_list looks like it is passed by value, but its not really,
    // and vswprintf, at least on GCC munges it. So we must use va_copy() to do this safely
    // @see http://en.cppreference.com/w/cpp/utility/variadic/va_copy
    va_list argListCopy ;
    va_copy(argListCopy, argsList);

    // Assume only reason for failure is not enuf bytes, so allocate more.
    // If I'm wrong, we'll just runout of memory and throw out...
    while (::vswprintf (msgBuf, msgBuf.GetSize (), useFormat, argListCopy) < 0) {
        msgBuf.GrowToSize (msgBuf.GetSize () * 2);
        va_end (argListCopy);
        va_copy (argListCopy, argsList);
    }
    va_end (argListCopy);
    Assert (::wcslen (msgBuf) < msgBuf.GetSize ());
    return wstring (msgBuf);
}
DISABLE_COMPILER_MSC_WARNING_END(6262)

wstring Characters::CString::Format (const wchar_t* format, ...)
{
    va_list     argsList;
    va_start (argsList, format);
    wstring tmp = FormatV (format, argsList);
    va_end (argsList);
    return tmp;
}

/*
 ********************************************************************************
 ********************************* LimitLength **********************************
 ********************************************************************************
 */
namespace   {
    template    <typename STRING>
    inline  STRING  LimitLength_HLPR (const STRING& str, size_t maxLen, bool keepLeft, const STRING& kELIPSIS)
    {
        if (str.length () <= maxLen) {
            return str;
        }
        size_t  useLen  =   maxLen;
        if (useLen > kELIPSIS.length ()) {
            useLen -= kELIPSIS.length ();
        }
        else {
            useLen = 0;
        }
        if (keepLeft) {
            return str.substr (0, useLen) + kELIPSIS;
        }
        else {
            return kELIPSIS + str.substr (str.length () - useLen);
        }
    }
}
string  Characters::CString::LimitLength (const string& str, size_t maxLen, bool keepLeft)
{
    return LimitLength_HLPR<string> (str, maxLen, keepLeft, "...");
}

wstring Characters::CString::LimitLength (const wstring& str, size_t maxLen, bool keepLeft)
{
    return LimitLength_HLPR<wstring> (str, maxLen, keepLeft, L"...");
}

/*
 ********************************************************************************
 *************************** StripTrailingCharIfAny *****************************
 ********************************************************************************
 */
namespace   {
    template    <typename STRING>
    inline  STRING  StripTrailingCharIfAny_HLPR (const STRING& str, typename STRING::value_type c)
    {
        if (str.size () > 0 and str[str.size () - 1] == c) {
            STRING  tmp =   str;
            tmp.erase (tmp.size () - 1);
            return tmp;
        }
        return str;
    }
}

string  Characters::CString::StripTrailingCharIfAny (const string& s, char c)
{
    return StripTrailingCharIfAny_HLPR (s, c);
}

wstring Characters::CString::StripTrailingCharIfAny (const wstring& s, wchar_t c)
{
    return StripTrailingCharIfAny_HLPR (s, c);
}

/*
 ********************************************************************************
 ********************************* Float2String *********************************
 ********************************************************************************
 */
wstring Characters::CString::Float2String (double f)
{
    if (std::isnan (f)) {
        return wstring ();
    }
    wstringstream s;
    s.imbue (locale ("C"));
    s << f;
    return s.str ();
}

/*
 ********************************************************************************
 ****************************** HexString2Int ***********************************
 ********************************************************************************
 */
unsigned int Characters::CString::HexString2Int (const string& s)
{
    using   std::numeric_limits;
    unsigned    long    l   =   strtoul (s.c_str (), nullptr, 16);
    if (l >= numeric_limits<unsigned int>::max ()) {
        return numeric_limits<unsigned int>::max ();
    }
    return l;
}

unsigned int Characters::CString::HexString2Int (const wchar_t* s)
{
    using   std::numeric_limits;
    RequireNotNull (s);
    unsigned    long    l   =   wcstoul (s, nullptr, 16);
    if (l >= numeric_limits<unsigned int>::max ()) {
        return numeric_limits<unsigned int>::max ();
    }
    return l;
}

unsigned int Characters::CString::HexString2Int (const wstring& s)
{
    using   std::numeric_limits;
    unsigned    long    l   =   wcstoul (s.c_str (), nullptr, 16);
    if (l >= numeric_limits<unsigned int>::max ()) {
        return numeric_limits<unsigned int>::max ();
    }
    return l;
}

/*
 ********************************************************************************
 ********************************* String2Int ***********************************
 ********************************************************************************
 */
long long int Characters::CString::Private_::String2Int_ (const string& s)
{
    using   std::numeric_limits;
    // nothing needed todo to pin the value to min/max
    return strtoll (s.c_str (), nullptr, 10);
}

long long int Characters::CString::Private_::String2Int_ (const wstring& s)
{
    using   std::numeric_limits;
    unsigned    long long int    l   =   wcstoll (s.c_str (), nullptr, 10);
    return l;
}

/*
 ********************************************************************************
 ********************************* String2UInt ***********************************
 ********************************************************************************
 */
unsigned long long int Characters::CString::Private_::String2UInt_ (const string& s)
{
    using   std::numeric_limits;
    // nothing needed todo to pin the value to min/max
    unsigned    long long int    l = strtoull (s.c_str (), nullptr, 10);
    return l;
}

unsigned long long int Characters::CString::Private_::String2UInt_ (const wstring& s)
{
    using   std::numeric_limits;
    long long int    l   =   wcstoull (s.c_str (), nullptr, 10);
    return l;
}

/*
 ********************************************************************************
 ********************************* String2Float *********************************
 ********************************************************************************
 */
double  Characters::CString::String2Float (const string& s)
{
    char*   e   =   nullptr;
    double  d   =   strtod (s.c_str (), &e);
    if (d == 0) {
        if (s.c_str () == e) {
            return Math::nan<double> ();
        }
    }
    return d;
}

double  Characters::CString::String2Float (const wchar_t* s)
{
    RequireNotNull (s);
    wchar_t*    e   =   nullptr;
    double  d   =   wcstod (s, &e);
    if (d == 0) {
        if (s == e) {
            return Math::nan<double> ();
        }
    }
    return d;
}

double  Characters::CString::String2Float (const wstring& s)
{
    wchar_t*    e   =   nullptr;
    double  d   =   wcstod (s.c_str (), &e);
    if (d == 0) {
        if (s.c_str () == e) {
            return Math::nan<double> ();
        }
    }
    return d;
}
<|endoftext|>


<commit_before>#include <algorithm>
#include <future>
#include <stdio.h>

#include "Halide.h"

using namespace Halide;
using namespace Halide::BoundaryConditions;

Var x("x"), y("y"), xo("xo"), yo("yo"), xi("xi"), yi("yi");

template <typename T>
bool expect_eq(T actual, T expected) {
    if (expected != actual) {
        fprintf(stderr, "Failed: expected %d, actual %d\n", (int) expected, (int) actual);
        return false;
    }
    return true;
}

void schedule_test(Func f, int vector_width, const Target &t) {
    if (vector_width != 1) {
        f.vectorize(x, vector_width);
    }
    if (t.has_gpu_feature() && vector_width <= 16) {
        f.gpu_tile(x, y, xo, yo, xi, yi, 2, 2);
    } else if (t.features_any_of({Target::HVX_64, Target::HVX_128})) {
        // TODO: Non-native vector widths hang the compiler here.
        //f.hexagon();
    }
}

template <typename T>
bool check_constant_exterior(const Buffer<T> &input, T exterior, Func f,
                             int test_min_x, int test_extent_x, int test_min_y, int test_extent_y,
                             int vector_width,
                             Target t) {
    bool success = true;

    Buffer<T> result(test_extent_x, test_extent_y);
    result.set_min(test_min_x, test_min_y);
    f = lambda(x, y, f(x, y));
    schedule_test(f, vector_width, t);
    f.realize(result, t);
    result.copy_to_host();

    for (int32_t y = test_min_y; y < test_min_y + test_extent_y; y++) {
        for (int32_t x = test_min_x; x < test_min_x + test_extent_x; x++) {
            if (x < 0 || y < 0 || x >= input.width() || y >= input.height()) {
                success &= expect_eq(result(x, y), exterior);
            } else {
                success &= expect_eq(result(x, y), input(x, y));
            }
        }
    }
    return success;
}

template <typename T>
bool check_repeat_edge(const Buffer<T> &input, Func f,
                       int test_min_x, int test_extent_x, int test_min_y, int test_extent_y,
                       int vector_width,
                       Target t) {
    bool success = true;

    Buffer<T> result(test_extent_x, test_extent_y);
    result.set_min(test_min_x, test_min_y);
    f = lambda(x, y, f(x, y));
    schedule_test(f, vector_width, t);
    f.realize(result, t);
    result.copy_to_host();

    for (int32_t y = test_min_y; y < test_min_y + test_extent_y; y++) {
        for (int32_t x = test_min_x; x < test_min_x + test_extent_x; x++) {
            int32_t clamped_y = std::min(input.height() - 1, std::max(0, y));
            int32_t clamped_x = std::min(input.width() - 1, std::max(0, x));
            success &= expect_eq(result(x, y), input(clamped_x, clamped_y));
        }
    }
    return success;
}

template <typename T>
bool check_repeat_image(const Buffer<T> &input, Func f,
                        int test_min_x, int test_extent_x, int test_min_y, int test_extent_y,
                        int vector_width,
                        Target t) {
    bool success = true;

    Buffer<T> result(test_extent_x, test_extent_y);
    result.set_min(test_min_x, test_min_y);
    f = lambda(x, y, f(x, y));
    schedule_test(f, vector_width, t);
    f.realize(result, t);
    result.copy_to_host();

    for (int32_t y = test_min_y; y < test_min_y + test_extent_y; y++) {
        for (int32_t x = test_min_x; x < test_min_x + test_extent_x; x++) {
            int32_t mapped_x = x;
            int32_t mapped_y = y;
            while (mapped_x < 0) mapped_x += input.width();
            while (mapped_x > input.width() - 1) mapped_x -= input.width();
            while (mapped_y < 0) mapped_y += input.height();
            while (mapped_y > input.height() - 1) mapped_y -= input.height();
            success &= expect_eq(result(x, y), input(mapped_x, mapped_y));
        }
    }
    return success;
}

template <typename T>
bool check_mirror_image(const Buffer<T> &input, Func f,
                        int test_min_x, int test_extent_x, int test_min_y, int test_extent_y,
                        int vector_width,
                        Target t) {
    bool success = true;

    Buffer<T> result(test_extent_x, test_extent_y);
    result.set_min(test_min_x, test_min_y);
    f = lambda(x, y, f(x, y));
    schedule_test(f, vector_width, t);
    f.realize(result, t);
    result.copy_to_host();

    for (int32_t y = test_min_y; y < test_min_y + test_extent_y; y++) {
        for (int32_t x = test_min_x; x < test_min_x + test_extent_x; x++) {
            int32_t mapped_x = (x < 0) ? -(x + 1) : x;
            mapped_x = mapped_x % (2 * input.width());
            if (mapped_x > (input.width() - 1)) {
                mapped_x = (2 * input.width() - 1) - mapped_x;
            }
            int32_t mapped_y = (y < 0) ? -(y + 1) : y;
            mapped_y = mapped_y % (2 * input.height());
            if (mapped_y > (input.height() - 1)) {
                mapped_y = (2 * input.height() - 1) - mapped_y;
            }
            success &= expect_eq(result(x, y), input(mapped_x, mapped_y));
        }
    }
    return success;
}

template <typename T>
bool check_mirror_interior(const Buffer<T> &input, Func f,
                           int test_min_x, int test_extent_x, int test_min_y, int test_extent_y,
                           int vector_width,
                           Target t) {
    bool success = true;

    Buffer<T> result(test_extent_x, test_extent_y);
    result.set_min(test_min_x, test_min_y);
    f = lambda(x, y, f(x, y));
    schedule_test(f, vector_width, t);
    f.realize(result, t);
    result.copy_to_host();

    for (int32_t y = test_min_y; y < test_min_y + test_extent_y; y++) {
        for (int32_t x = test_min_x; x < test_min_x + test_extent_x; x++) {
            int32_t mapped_x = abs(x) % (input.width() * 2 - 2);
            if (mapped_x > input.width() - 1) {
                mapped_x = input.width() * 2 - 2 - mapped_x;
            }
            int32_t mapped_y = abs(y) % (input.height() * 2 - 2);
            if (mapped_y > input.height() - 1) {
                mapped_y = input.height() * 2 - 2 - mapped_y;
            }

            success &= expect_eq(result(x, y), input(mapped_x, mapped_y));
        }
    }
    return success;
}

bool test_all(int vector_width, Target t) {
    bool success = true;

    const int W = 32;
    const int H = 32;
    Buffer<uint8_t> input(W, H);
    for (int32_t y = 0; y < H; y++) {
        for (int32_t x = 0; x < W; x++) {
            input(x, y) = x + y * W;
        }
    }

    Func input_f("input_f");
    input_f(x, y) = input(x, y);

    // repeat_edge:
    {
        const int32_t test_min = -25;
        const int32_t test_extent = 100;

        // Func input.
        success &= check_repeat_edge(
            input,
            repeat_edge(input_f, 0, W, 0, H),
            test_min, test_extent, test_min, test_extent,
            vector_width, t);
        // Image input.
        success &= check_repeat_edge(
            input,
            repeat_edge(input, 0, W, 0, H),
            test_min, test_extent, test_min, test_extent,
            vector_width, t);
        // Undefined bounds.
        success &= check_repeat_edge(
            input,
            repeat_edge(input, Expr(), Expr(), 0, H),
            0, W, test_min, test_extent,
            vector_width, t);
        success &= check_repeat_edge(
            input,
            repeat_edge(input, 0, W, Expr(), Expr()),
            test_min, test_extent, 0, H,
            vector_width, t);
        // Implicitly determined bounds.
        success &= check_repeat_edge(
            input,
            repeat_edge(input),
            test_min, test_extent, test_min, test_extent,
            vector_width, t);
    }

    // constant_exterior:
    {
        const int32_t test_min = -25;
        const int32_t test_extent = 100;

        const uint8_t exterior = 42;

        // Func input.
        success &= check_constant_exterior(
            input, exterior,
            constant_exterior(input_f, exterior, 0, W, 0, H),
            test_min, test_extent, test_min, test_extent,
            vector_width, t);
        // Image input.
        success &= check_constant_exterior(
            input, exterior,
            constant_exterior(input, exterior, 0, W, 0, H),
            test_min, test_extent, test_min, test_extent,
            vector_width, t);
        // Undefined bounds.
        success &= check_constant_exterior(
            input, exterior,
            constant_exterior(input, exterior, Expr(), Expr(), 0, H),
            0, W, test_min, test_extent,
            vector_width, t);
        success &= check_constant_exterior(
            input, exterior,
            constant_exterior(input, exterior, 0, W, Expr(), Expr()),
            test_min, test_extent, 0, H,
            vector_width, t);
        // Implicitly determined bounds.
        success &= check_constant_exterior(
            input, exterior,
            constant_exterior(input, exterior),
            test_min, test_extent, test_min, test_extent,
            vector_width, t);
    }

    // repeat_image:
    {
        const int32_t test_min = -25;
        const int32_t test_extent = 100;

        // Func input.
        success &= check_repeat_image(
            input,
            repeat_image(input_f, 0, W, 0, H),
            test_min, test_extent, test_min, test_extent,
            vector_width, t);
        // Image input.
        success &= check_repeat_image(
            input,
            repeat_image(input, 0, W, 0, H),
            test_min, test_extent, test_min, test_extent,
            vector_width, t);
        // Undefined bounds.
        success &= check_repeat_image(
            input,
            repeat_image(input, Expr(), Expr(), 0, H),
            0, W, test_min, test_extent,
            vector_width, t);
        success &= check_repeat_image(
            input,
            repeat_image(input, 0, W, Expr(), Expr()),
            test_min, test_extent, 0, H,
            vector_width, t);
        // Implicitly determined bounds.
        success &= check_repeat_image(
            input,
            repeat_image(input),
            test_min, test_extent, test_min, test_extent,
            vector_width, t);
    }

    // mirror_image:
    {
        const int32_t test_min = -25;
        const int32_t test_extent = 100;

        // Func input.
        success &= check_mirror_image(
            input,
            mirror_image(input_f, 0, W, 0, H),
            test_min, test_extent, test_min, test_extent,
            vector_width, t);
        // Image input.
        success &= check_mirror_image(
            input,
            mirror_image(input, 0, W, 0, H),
            test_min, test_extent, test_min, test_extent,
            vector_width, t);
        // Undefined bounds.
        success &= check_mirror_image(
            input,
            mirror_image(input, Expr(), Expr(), 0, H),
            0, W, test_min, test_extent,
            vector_width, t);
        success &= check_mirror_image(
            input,
            mirror_image(input, 0, W, Expr(), Expr()),
            test_min, test_extent, 0, H,
            vector_width, t);
        // Implicitly determined bounds.
        success &= check_mirror_image(
            input,
            mirror_image(input),
            test_min, test_extent, test_min, test_extent,
            vector_width, t);
    }

    // mirror_interior:
    {
        const int32_t test_min = -25;
        const int32_t test_extent = 100;

        // Func input.
        success &= check_mirror_interior(
            input,
            mirror_interior(input_f, 0, W, 0, H),
            test_min, test_extent, test_min, test_extent,
            vector_width, t);
        // Image input.
        success &= check_mirror_interior(
            input,
            mirror_interior(input, 0, W, 0, H),
            test_min, test_extent, test_min, test_extent,
            vector_width, t);
        // Undefined bounds.
        success &= check_mirror_interior(
            input,
            mirror_interior(input, Expr(), Expr(), 0, H),
            0, W, test_min, test_extent,
            vector_width, t);
        success &= check_mirror_interior(
            input,
            mirror_interior(input, 0, W, Expr(), Expr()),
            test_min, test_extent, 0, H,
            vector_width, t);
        // Implicitly determined bounds.
        success &= check_mirror_interior(
            input,
            mirror_interior(input),
            test_min, test_extent, test_min, test_extent,
            vector_width, t);
    }

    return success;
}

int main(int argc, char **argv) {
    Target target = get_jit_target_from_environment();

    std::vector<std::future<bool>> futures;
    for (int vector_width = 1; vector_width <= 32; vector_width *= 2) {
        std::cout << "Testing vector_width: " << vector_width << "\n";
        futures.push_back(std::async(test_all, vector_width, target));
    }

    bool success = true;
    for (auto &f : futures) {
        f.wait();
        success &= f.get();
    }

    if (!success) {
        fprintf(stderr, "Failed!\n");
        return -1;
    }

    printf("Success!\n");
    return 0;
}
<commit_msg>Remove unnecessary wait()<commit_after>#include <algorithm>
#include <future>
#include <stdio.h>

#include "Halide.h"

using namespace Halide;
using namespace Halide::BoundaryConditions;

Var x("x"), y("y"), xo("xo"), yo("yo"), xi("xi"), yi("yi");

template <typename T>
bool expect_eq(T actual, T expected) {
    if (expected != actual) {
        fprintf(stderr, "Failed: expected %d, actual %d\n", (int) expected, (int) actual);
        return false;
    }
    return true;
}

void schedule_test(Func f, int vector_width, const Target &t) {
    if (vector_width != 1) {
        f.vectorize(x, vector_width);
    }
    if (t.has_gpu_feature() && vector_width <= 16) {
        f.gpu_tile(x, y, xo, yo, xi, yi, 2, 2);
    } else if (t.features_any_of({Target::HVX_64, Target::HVX_128})) {
        // TODO: Non-native vector widths hang the compiler here.
        //f.hexagon();
    }
}

template <typename T>
bool check_constant_exterior(const Buffer<T> &input, T exterior, Func f,
                             int test_min_x, int test_extent_x, int test_min_y, int test_extent_y,
                             int vector_width,
                             Target t) {
    bool success = true;

    Buffer<T> result(test_extent_x, test_extent_y);
    result.set_min(test_min_x, test_min_y);
    f = lambda(x, y, f(x, y));
    schedule_test(f, vector_width, t);
    f.realize(result, t);
    result.copy_to_host();

    for (int32_t y = test_min_y; y < test_min_y + test_extent_y; y++) {
        for (int32_t x = test_min_x; x < test_min_x + test_extent_x; x++) {
            if (x < 0 || y < 0 || x >= input.width() || y >= input.height()) {
                success &= expect_eq(result(x, y), exterior);
            } else {
                success &= expect_eq(result(x, y), input(x, y));
            }
        }
    }
    return success;
}

template <typename T>
bool check_repeat_edge(const Buffer<T> &input, Func f,
                       int test_min_x, int test_extent_x, int test_min_y, int test_extent_y,
                       int vector_width,
                       Target t) {
    bool success = true;

    Buffer<T> result(test_extent_x, test_extent_y);
    result.set_min(test_min_x, test_min_y);
    f = lambda(x, y, f(x, y));
    schedule_test(f, vector_width, t);
    f.realize(result, t);
    result.copy_to_host();

    for (int32_t y = test_min_y; y < test_min_y + test_extent_y; y++) {
        for (int32_t x = test_min_x; x < test_min_x + test_extent_x; x++) {
            int32_t clamped_y = std::min(input.height() - 1, std::max(0, y));
            int32_t clamped_x = std::min(input.width() - 1, std::max(0, x));
            success &= expect_eq(result(x, y), input(clamped_x, clamped_y));
        }
    }
    return success;
}

template <typename T>
bool check_repeat_image(const Buffer<T> &input, Func f,
                        int test_min_x, int test_extent_x, int test_min_y, int test_extent_y,
                        int vector_width,
                        Target t) {
    bool success = true;

    Buffer<T> result(test_extent_x, test_extent_y);
    result.set_min(test_min_x, test_min_y);
    f = lambda(x, y, f(x, y));
    schedule_test(f, vector_width, t);
    f.realize(result, t);
    result.copy_to_host();

    for (int32_t y = test_min_y; y < test_min_y + test_extent_y; y++) {
        for (int32_t x = test_min_x; x < test_min_x + test_extent_x; x++) {
            int32_t mapped_x = x;
            int32_t mapped_y = y;
            while (mapped_x < 0) mapped_x += input.width();
            while (mapped_x > input.width() - 1) mapped_x -= input.width();
            while (mapped_y < 0) mapped_y += input.height();
            while (mapped_y > input.height() - 1) mapped_y -= input.height();
            success &= expect_eq(result(x, y), input(mapped_x, mapped_y));
        }
    }
    return success;
}

template <typename T>
bool check_mirror_image(const Buffer<T> &input, Func f,
                        int test_min_x, int test_extent_x, int test_min_y, int test_extent_y,
                        int vector_width,
                        Target t) {
    bool success = true;

    Buffer<T> result(test_extent_x, test_extent_y);
    result.set_min(test_min_x, test_min_y);
    f = lambda(x, y, f(x, y));
    schedule_test(f, vector_width, t);
    f.realize(result, t);
    result.copy_to_host();

    for (int32_t y = test_min_y; y < test_min_y + test_extent_y; y++) {
        for (int32_t x = test_min_x; x < test_min_x + test_extent_x; x++) {
            int32_t mapped_x = (x < 0) ? -(x + 1) : x;
            mapped_x = mapped_x % (2 * input.width());
            if (mapped_x > (input.width() - 1)) {
                mapped_x = (2 * input.width() - 1) - mapped_x;
            }
            int32_t mapped_y = (y < 0) ? -(y + 1) : y;
            mapped_y = mapped_y % (2 * input.height());
            if (mapped_y > (input.height() - 1)) {
                mapped_y = (2 * input.height() - 1) - mapped_y;
            }
            success &= expect_eq(result(x, y), input(mapped_x, mapped_y));
        }
    }
    return success;
}

template <typename T>
bool check_mirror_interior(const Buffer<T> &input, Func f,
                           int test_min_x, int test_extent_x, int test_min_y, int test_extent_y,
                           int vector_width,
                           Target t) {
    bool success = true;

    Buffer<T> result(test_extent_x, test_extent_y);
    result.set_min(test_min_x, test_min_y);
    f = lambda(x, y, f(x, y));
    schedule_test(f, vector_width, t);
    f.realize(result, t);
    result.copy_to_host();

    for (int32_t y = test_min_y; y < test_min_y + test_extent_y; y++) {
        for (int32_t x = test_min_x; x < test_min_x + test_extent_x; x++) {
            int32_t mapped_x = abs(x) % (input.width() * 2 - 2);
            if (mapped_x > input.width() - 1) {
                mapped_x = input.width() * 2 - 2 - mapped_x;
            }
            int32_t mapped_y = abs(y) % (input.height() * 2 - 2);
            if (mapped_y > input.height() - 1) {
                mapped_y = input.height() * 2 - 2 - mapped_y;
            }

            success &= expect_eq(result(x, y), input(mapped_x, mapped_y));
        }
    }
    return success;
}

bool test_all(int vector_width, Target t) {
    bool success = true;

    const int W = 32;
    const int H = 32;
    Buffer<uint8_t> input(W, H);
    for (int32_t y = 0; y < H; y++) {
        for (int32_t x = 0; x < W; x++) {
            input(x, y) = x + y * W;
        }
    }

    Func input_f("input_f");
    input_f(x, y) = input(x, y);

    // repeat_edge:
    {
        const int32_t test_min = -25;
        const int32_t test_extent = 100;

        // Func input.
        success &= check_repeat_edge(
            input,
            repeat_edge(input_f, 0, W, 0, H),
            test_min, test_extent, test_min, test_extent,
            vector_width, t);
        // Image input.
        success &= check_repeat_edge(
            input,
            repeat_edge(input, 0, W, 0, H),
            test_min, test_extent, test_min, test_extent,
            vector_width, t);
        // Undefined bounds.
        success &= check_repeat_edge(
            input,
            repeat_edge(input, Expr(), Expr(), 0, H),
            0, W, test_min, test_extent,
            vector_width, t);
        success &= check_repeat_edge(
            input,
            repeat_edge(input, 0, W, Expr(), Expr()),
            test_min, test_extent, 0, H,
            vector_width, t);
        // Implicitly determined bounds.
        success &= check_repeat_edge(
            input,
            repeat_edge(input),
            test_min, test_extent, test_min, test_extent,
            vector_width, t);
    }

    // constant_exterior:
    {
        const int32_t test_min = -25;
        const int32_t test_extent = 100;

        const uint8_t exterior = 42;

        // Func input.
        success &= check_constant_exterior(
            input, exterior,
            constant_exterior(input_f, exterior, 0, W, 0, H),
            test_min, test_extent, test_min, test_extent,
            vector_width, t);
        // Image input.
        success &= check_constant_exterior(
            input, exterior,
            constant_exterior(input, exterior, 0, W, 0, H),
            test_min, test_extent, test_min, test_extent,
            vector_width, t);
        // Undefined bounds.
        success &= check_constant_exterior(
            input, exterior,
            constant_exterior(input, exterior, Expr(), Expr(), 0, H),
            0, W, test_min, test_extent,
            vector_width, t);
        success &= check_constant_exterior(
            input, exterior,
            constant_exterior(input, exterior, 0, W, Expr(), Expr()),
            test_min, test_extent, 0, H,
            vector_width, t);
        // Implicitly determined bounds.
        success &= check_constant_exterior(
            input, exterior,
            constant_exterior(input, exterior),
            test_min, test_extent, test_min, test_extent,
            vector_width, t);
    }

    // repeat_image:
    {
        const int32_t test_min = -25;
        const int32_t test_extent = 100;

        // Func input.
        success &= check_repeat_image(
            input,
            repeat_image(input_f, 0, W, 0, H),
            test_min, test_extent, test_min, test_extent,
            vector_width, t);
        // Image input.
        success &= check_repeat_image(
            input,
            repeat_image(input, 0, W, 0, H),
            test_min, test_extent, test_min, test_extent,
            vector_width, t);
        // Undefined bounds.
        success &= check_repeat_image(
            input,
            repeat_image(input, Expr(), Expr(), 0, H),
            0, W, test_min, test_extent,
            vector_width, t);
        success &= check_repeat_image(
            input,
            repeat_image(input, 0, W, Expr(), Expr()),
            test_min, test_extent, 0, H,
            vector_width, t);
        // Implicitly determined bounds.
        success &= check_repeat_image(
            input,
            repeat_image(input),
            test_min, test_extent, test_min, test_extent,
            vector_width, t);
    }

    // mirror_image:
    {
        const int32_t test_min = -25;
        const int32_t test_extent = 100;

        // Func input.
        success &= check_mirror_image(
            input,
            mirror_image(input_f, 0, W, 0, H),
            test_min, test_extent, test_min, test_extent,
            vector_width, t);
        // Image input.
        success &= check_mirror_image(
            input,
            mirror_image(input, 0, W, 0, H),
            test_min, test_extent, test_min, test_extent,
            vector_width, t);
        // Undefined bounds.
        success &= check_mirror_image(
            input,
            mirror_image(input, Expr(), Expr(), 0, H),
            0, W, test_min, test_extent,
            vector_width, t);
        success &= check_mirror_image(
            input,
            mirror_image(input, 0, W, Expr(), Expr()),
            test_min, test_extent, 0, H,
            vector_width, t);
        // Implicitly determined bounds.
        success &= check_mirror_image(
            input,
            mirror_image(input),
            test_min, test_extent, test_min, test_extent,
            vector_width, t);
    }

    // mirror_interior:
    {
        const int32_t test_min = -25;
        const int32_t test_extent = 100;

        // Func input.
        success &= check_mirror_interior(
            input,
            mirror_interior(input_f, 0, W, 0, H),
            test_min, test_extent, test_min, test_extent,
            vector_width, t);
        // Image input.
        success &= check_mirror_interior(
            input,
            mirror_interior(input, 0, W, 0, H),
            test_min, test_extent, test_min, test_extent,
            vector_width, t);
        // Undefined bounds.
        success &= check_mirror_interior(
            input,
            mirror_interior(input, Expr(), Expr(), 0, H),
            0, W, test_min, test_extent,
            vector_width, t);
        success &= check_mirror_interior(
            input,
            mirror_interior(input, 0, W, Expr(), Expr()),
            test_min, test_extent, 0, H,
            vector_width, t);
        // Implicitly determined bounds.
        success &= check_mirror_interior(
            input,
            mirror_interior(input),
            test_min, test_extent, test_min, test_extent,
            vector_width, t);
    }

    return success;
}

int main(int argc, char **argv) {
    Target target = get_jit_target_from_environment();

    std::vector<std::future<bool>> futures;
    for (int vector_width = 1; vector_width <= 32; vector_width *= 2) {
        std::cout << "Testing vector_width: " << vector_width << "\n";
        futures.push_back(std::async(test_all, vector_width, target));
    }

    bool success = true;
    for (auto &f : futures) {
        success &= f.get();
    }

    if (!success) {
        fprintf(stderr, "Failed!\n");
        return -1;
    }

    printf("Success!\n");
    return 0;
}
<|endoftext|>