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

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "tensorflow/lite/delegates/gpu/cl/kernels/strided_slice.h"

#include <string>

#include "tensorflow/lite/delegates/gpu/cl/kernels/util.h"
#include "tensorflow/lite/delegates/gpu/cl/kernels/work_group_picking.h"

namespace tflite {
namespace gpu {
namespace cl {
namespace {

std::string GetStridedSliceCode(
    const OperationDef& op_def, bool alignedx4,
    const std::vector<ElementwiseOperation*>& linked_operations) {
  TensorCodeGenerator src_tensor(
      "src_data",
      WHSBPoint{"src_size.x", "src_size.y", "src_size.z", "src_size.w"},
      op_def.src_tensors[0]);
  TensorCodeGenerator dst_tensor(
      "dst_data",
      WHSBPoint{"dst_size.x", "dst_size.y", "dst_size.z", "dst_size.w"},
      op_def.dst_tensors[0]);

  const std::string dst_batch = op_def.IsBatchSupported() ? "B" : "";
  std::string c = GetCommonDefines(op_def.precision);
  c += "__kernel void main_function(\n";
  c += src_tensor.GetDeclaration(AccessType::READ);
  c += GetArgsDeclaration(linked_operations);
  c += dst_tensor.GetDeclaration(AccessType::WRITE) + ",\n";
  c += "    int4 offset,            \n";
  c += "    int4 stride,            \n";
  c += "    int4 src_size,             \n";
  c += "    int4 dst_size              \n";
  c += ") {\n";
  if (op_def.IsBatchSupported()) {
    c += "  int linear_id = get_global_id(0);\n";
    c += "  int X = linear_id / dst_size.w;\n";
    c += "  int B = linear_id % dst_size.w;\n";
  } else {
    c += "  int X = get_global_id(0);\n";
  }
  c += "  int Y = get_global_id(1);\n";
  c += "  int Z = get_global_id(2);\n";
  c += "  if (X >= dst_size.x || Y >= dst_size.y || Z >= dst_size.z) { \n";
  c += "    return; \n";
  c += "  } \n";
  c += "  int s_x = X * stride.x + offset.x;\n";
  c += "  int s_y = Y * stride.y + offset.y;\n";
  if (op_def.IsBatchSupported()) {
    c += "  int s_b = B * stride.w + offset.w;\n";
  }
  const std::string src_batch = op_def.IsBatchSupported() ? "s_b" : "";
  if (alignedx4) {
    c += "  int s_z = Z + offset.z;\n";
    c += "  FLT4 result = " +
         src_tensor.ReadWHSB("s_x", "s_y", "s_z", src_batch) + ";\n";
  } else {
    c += "  FLT4 result;\n";
    const std::string postfixes[] = {"x", "y", "z", "w"};
    for (int i = 0; i < 4; ++i) {
      c += "  {\n";
      const std::string channel = "(Z * 4 + " + std::to_string(i) + ")";
      c += "    int s_ch = " + channel + " * stride.z + offset.z;\n";
      c += "    int s_z = s_ch >> 2;\n";
      c += "    int s_z_rem = s_ch & 3;\n";
      c += "    FLT4 t = " +
           src_tensor.ReadWHSB("s_x", "s_y", "s_z", src_batch) + ";\n";
      c += "    FLT t_ar[4] = {t.x, t.y, t.z, t.w};\n";
      c += "    result." + postfixes[i] + " = t_ar[s_z_rem];\n";
      c += "  }\n";
    }
  }
  std::string x_3dcoord =
      op_def.IsBatchSupported() ? "X * dst_size.w + B" : "X";
  const LinkingContext context{"result", x_3dcoord, "Y", "Z"};
  c += PostProcess(linked_operations, context);
  c += "  " + dst_tensor.WriteWHSB("result", "X", "Y", "Z", dst_batch);
  c += "}\n";
  return c;
}

bool Is4Alighed(const SliceAttributes& attr) {
  return attr.strides.c == 1 && attr.starts.c % 4 == 0;
}

int4 GetOffset(const SliceAttributes& attr, int src_width, int src_height,
               int src_channels, int src_batch) {
  int4 offset;
  if (attr.strides.w > 0) {
    offset.x = attr.starts.w;
  } else {
    if (attr.ends.w > 0) {
      offset.x = attr.ends.w;
    } else {
      offset.x = src_width + attr.ends.w;
    }
  }
  if (attr.strides.h > 0) {
    offset.y = attr.starts.h;
  } else {
    if (attr.ends.h > 0) {
      offset.y = attr.ends.h;
    } else {
      offset.y = src_height + attr.ends.h;
    }
  }
  if (attr.strides.c > 0) {
    offset.z = attr.starts.c;
  } else {
    if (attr.ends.c > 0) {
      offset.z = attr.ends.c;
    } else {
      offset.z = src_channels + attr.ends.c;
    }
  }
  if (Is4Alighed(attr)) {
    offset.z /= 4;
  }
  if (attr.strides.b > 0) {
    offset.w = attr.starts.b;
  } else {
    if (attr.ends.b > 0) {
      offset.w = attr.ends.b;
    } else {
      offset.w = src_batch + attr.ends.b;
    }
  }
  return offset;
}

}  // namespace

StridedSlice::StridedSlice(const OperationDef& definition,
                           const SliceAttributes& attr)
    : GPUOperation(definition), attributes_(attr), work_group_size_(8, 4, 1) {}

StridedSlice::StridedSlice(StridedSlice&& operation)
    : GPUOperation(std::move(operation)),
      attributes_(operation.attributes_),
      kernel_(std::move(operation.kernel_)),
      work_group_size_(operation.work_group_size_) {}

StridedSlice& StridedSlice::operator=(StridedSlice&& operation) {
  if (this != &operation) {
    attributes_ = operation.attributes_;
    kernel_ = std::move(operation.kernel_);
    std::swap(work_group_size_, operation.work_group_size_);
    GPUOperation::operator=(std::move(operation));
  }
  return *this;
}

Status StridedSlice::Compile(const CreationContext& creation_context) {
  const auto code = GetStridedSliceCode(definition_, Is4Alighed(attributes_),
                                        linked_operations_);
  return creation_context.cache->GetOrCreateCLKernel(
      code, "main_function", *creation_context.context,
      *creation_context.device, &kernel_);
}

Status StridedSlice::BindArguments() {
  kernel_.ResetBindingCounter();
  RETURN_IF_ERROR(kernel_.SetMemoryAuto(src_[0]->GetMemoryPtr()));
  RETURN_IF_ERROR(BindArgs(&kernel_, linked_operations_));
  RETURN_IF_ERROR(kernel_.SetMemoryAuto(dst_[0]->GetMemoryPtrForWriting()));
  int4 offset = GetOffset(attributes_, src_[0]->Width(), src_[0]->Height(),
                          src_[0]->Channels(), src_[0]->Batch());
  RETURN_IF_ERROR(kernel_.SetBytesAuto(offset));
  RETURN_IF_ERROR(
      kernel_.SetBytesAuto(int4(attributes_.strides.w, attributes_.strides.h,
                                attributes_.strides.c, attributes_.strides.b)));
  RETURN_IF_ERROR(kernel_.SetBytesAuto(src_[0]->GetWHSB()));
  RETURN_IF_ERROR(kernel_.SetBytesAuto(dst_[0]->GetWHSB()));
  return OkStatus();
}

int3 StridedSlice::GetGridSize() const {
  const int grid_x = dst_[0]->Width() * dst_[0]->Batch();
  const int grid_y = dst_[0]->Height();
  const int grid_z = dst_[0]->Slices();
  return int3(grid_x, grid_y, grid_z);
}

Status StridedSlice::Tune(const TuningParameters& params) {
  RETURN_IF_ERROR(BindArguments());
  return GetBestWorkGroup(params, kernel_, GetGridSize(), &work_group_size_);
}

Status StridedSlice::AddToQueue(CLCommandQueue* queue) {
  RETURN_IF_ERROR(BindArguments());
  return queue->DispatchImplicit(kernel_, GetGridSize(), work_group_size_);
}

StridedSlice CreateStridedSlice(const OperationDef& definition,
                                const SliceAttributes& attr) {
  return StridedSlice(definition, attr);
}

}  // namespace cl
}  // namespace gpu
}  // namespace tflite
<commit_msg>Fixed reading out of bounds in StridedSlice.<commit_after>/* Copyright 2019 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "tensorflow/lite/delegates/gpu/cl/kernels/strided_slice.h"

#include <string>

#include "tensorflow/lite/delegates/gpu/cl/kernels/util.h"
#include "tensorflow/lite/delegates/gpu/cl/kernels/work_group_picking.h"

namespace tflite {
namespace gpu {
namespace cl {
namespace {

std::string GetStridedSliceCode(
    const OperationDef& op_def, bool alignedx4,
    const std::vector<ElementwiseOperation*>& linked_operations) {
  TensorCodeGenerator src_tensor(
      "src_data",
      WHSBPoint{"src_size.x", "src_size.y", "src_size.z", "src_size.w"},
      op_def.src_tensors[0]);
  TensorCodeGenerator dst_tensor(
      "dst_data",
      WHSBPoint{"dst_size.x", "dst_size.y", "dst_size.z", "dst_size.w"},
      op_def.dst_tensors[0]);

  const std::string dst_batch = op_def.IsBatchSupported() ? "B" : "";
  std::string c = GetCommonDefines(op_def.precision);
  c += "__kernel void main_function(\n";
  c += src_tensor.GetDeclaration(AccessType::READ);
  c += GetArgsDeclaration(linked_operations);
  c += dst_tensor.GetDeclaration(AccessType::WRITE) + ",\n";
  c += "    int4 offset,            \n";
  c += "    int4 stride,            \n";
  c += "    int4 src_size,             \n";
  c += "    int4 dst_size              \n";
  c += ") {\n";
  if (op_def.IsBatchSupported()) {
    c += "  int linear_id = get_global_id(0);\n";
    c += "  int X = linear_id / dst_size.w;\n";
    c += "  int B = linear_id % dst_size.w;\n";
  } else {
    c += "  int X = get_global_id(0);\n";
  }
  c += "  int Y = get_global_id(1);\n";
  c += "  int Z = get_global_id(2);\n";
  c += "  if (X >= dst_size.x || Y >= dst_size.y || Z >= dst_size.z) { \n";
  c += "    return; \n";
  c += "  } \n";
  c += "  int s_x = X * stride.x + offset.x;\n";
  c += "  int s_y = Y * stride.y + offset.y;\n";
  if (op_def.IsBatchSupported()) {
    c += "  int s_b = B * stride.w + offset.w;\n";
  }
  const std::string src_batch = op_def.IsBatchSupported() ? "s_b" : "";
  if (alignedx4) {
    c += "  int s_z = Z + offset.z;\n";
    c += "  FLT4 result = " +
         src_tensor.ReadWHSB("s_x", "s_y", "s_z", src_batch) + ";\n";
  } else {
    c += "  FLT4 result;\n";
    const std::string postfixes[] = {"x", "y", "z", "w"};
    for (int i = 0; i < 4; ++i) {
      c += "  {\n";
      const std::string channel = "(Z * 4 + " + std::to_string(i) + ")";
      c += "    int s_ch = " + channel + " * stride.z + offset.z;\n";
      c += "    int s_z = min(s_ch >> 2, src_size.z - 1);\n";
      c += "    int s_z_rem = s_ch & 3;\n";
      c += "    FLT4 t = " +
           src_tensor.ReadWHSB("s_x", "s_y", "s_z", src_batch) + ";\n";
      c += "    FLT t_ar[4] = {t.x, t.y, t.z, t.w};\n";
      c += "    result." + postfixes[i] + " = t_ar[s_z_rem];\n";
      c += "  }\n";
    }
  }
  std::string x_3dcoord =
      op_def.IsBatchSupported() ? "X * dst_size.w + B" : "X";
  const LinkingContext context{"result", x_3dcoord, "Y", "Z"};
  c += PostProcess(linked_operations, context);
  c += "  " + dst_tensor.WriteWHSB("result", "X", "Y", "Z", dst_batch);
  c += "}\n";
  return c;
}

bool Is4Alighed(const SliceAttributes& attr) {
  return attr.strides.c == 1 && attr.starts.c % 4 == 0;
}

int4 GetOffset(const SliceAttributes& attr, int src_width, int src_height,
               int src_channels, int src_batch) {
  int4 offset;
  if (attr.strides.w > 0) {
    offset.x = attr.starts.w;
  } else {
    if (attr.ends.w > 0) {
      offset.x = attr.ends.w;
    } else {
      offset.x = src_width + attr.ends.w;
    }
  }
  if (attr.strides.h > 0) {
    offset.y = attr.starts.h;
  } else {
    if (attr.ends.h > 0) {
      offset.y = attr.ends.h;
    } else {
      offset.y = src_height + attr.ends.h;
    }
  }
  if (attr.strides.c > 0) {
    offset.z = attr.starts.c;
  } else {
    if (attr.ends.c > 0) {
      offset.z = attr.ends.c;
    } else {
      offset.z = src_channels + attr.ends.c;
    }
  }
  if (Is4Alighed(attr)) {
    offset.z /= 4;
  }
  if (attr.strides.b > 0) {
    offset.w = attr.starts.b;
  } else {
    if (attr.ends.b > 0) {
      offset.w = attr.ends.b;
    } else {
      offset.w = src_batch + attr.ends.b;
    }
  }
  return offset;
}

}  // namespace

StridedSlice::StridedSlice(const OperationDef& definition,
                           const SliceAttributes& attr)
    : GPUOperation(definition), attributes_(attr), work_group_size_(8, 4, 1) {}

StridedSlice::StridedSlice(StridedSlice&& operation)
    : GPUOperation(std::move(operation)),
      attributes_(operation.attributes_),
      kernel_(std::move(operation.kernel_)),
      work_group_size_(operation.work_group_size_) {}

StridedSlice& StridedSlice::operator=(StridedSlice&& operation) {
  if (this != &operation) {
    attributes_ = operation.attributes_;
    kernel_ = std::move(operation.kernel_);
    std::swap(work_group_size_, operation.work_group_size_);
    GPUOperation::operator=(std::move(operation));
  }
  return *this;
}

Status StridedSlice::Compile(const CreationContext& creation_context) {
  const auto code = GetStridedSliceCode(definition_, Is4Alighed(attributes_),
                                        linked_operations_);
  return creation_context.cache->GetOrCreateCLKernel(
      code, "main_function", *creation_context.context,
      *creation_context.device, &kernel_);
}

Status StridedSlice::BindArguments() {
  kernel_.ResetBindingCounter();
  RETURN_IF_ERROR(kernel_.SetMemoryAuto(src_[0]->GetMemoryPtr()));
  RETURN_IF_ERROR(BindArgs(&kernel_, linked_operations_));
  RETURN_IF_ERROR(kernel_.SetMemoryAuto(dst_[0]->GetMemoryPtrForWriting()));
  int4 offset = GetOffset(attributes_, src_[0]->Width(), src_[0]->Height(),
                          src_[0]->Channels(), src_[0]->Batch());
  RETURN_IF_ERROR(kernel_.SetBytesAuto(offset));
  RETURN_IF_ERROR(
      kernel_.SetBytesAuto(int4(attributes_.strides.w, attributes_.strides.h,
                                attributes_.strides.c, attributes_.strides.b)));
  RETURN_IF_ERROR(kernel_.SetBytesAuto(src_[0]->GetWHSB()));
  RETURN_IF_ERROR(kernel_.SetBytesAuto(dst_[0]->GetWHSB()));
  return OkStatus();
}

int3 StridedSlice::GetGridSize() const {
  const int grid_x = dst_[0]->Width() * dst_[0]->Batch();
  const int grid_y = dst_[0]->Height();
  const int grid_z = dst_[0]->Slices();
  return int3(grid_x, grid_y, grid_z);
}

Status StridedSlice::Tune(const TuningParameters& params) {
  RETURN_IF_ERROR(BindArguments());
  return GetBestWorkGroup(params, kernel_, GetGridSize(), &work_group_size_);
}

Status StridedSlice::AddToQueue(CLCommandQueue* queue) {
  RETURN_IF_ERROR(BindArguments());
  return queue->DispatchImplicit(kernel_, GetGridSize(), work_group_size_);
}

StridedSlice CreateStridedSlice(const OperationDef& definition,
                                const SliceAttributes& attr) {
  return StridedSlice(definition, attr);
}

}  // namespace cl
}  // namespace gpu
}  // namespace tflite
<|endoftext|>


<commit_before>// Analysis task for Long Range Correlation (LRC) analysis using TPC data
// This includes a TList of AliLRCProcess objects that are processing LRC analysis
// for a given Eta window
// This task is worcking with ESD data only

// Author : Andrey Ivanov , St.Peterburg State University
// Email: Andrey.Ivanov@cern.ch

// Version line : 3.5
// Version 3.5.5

#include "TChain.h"
#include "TTree.h"
#include "AliVEvent.h"
#include "AliMCEvent.h"
#include "AliAnalysisManager.h"
#include "AliAnalysisTaskLRC.h"
#include <AliPID.h>

ClassImp(AliAnalysisTaskLRC)

//________________________________________________________________________
AliAnalysisTaskLRC::AliAnalysisTaskLRC(const char *name,Bool_t runKine)
  : AliAnalysisTaskSE(name),fMaxPtLimit(5.0),fMinPtLimit(0.0),fDropKineE(kFALSE), fLRCproc(0),fOutList(0),fRunKine(0)
{
  //Init

  fRunKine=runKine;

  // Constructor

  // Output slot #1 writes into a TList container for all histogramms
  DefineOutput(1, TList::Class());

}

// ---------------------------------------  Setters ------------------

//________________________________________________________________________
void AliAnalysisTaskLRC::UserCreateOutputObjects()
{
  // Create histograms

  //LRC processors init
  Int_t lLrcNum=fLRCproc.GetEntries();

  for(Int_t i=0; i < lLrcNum; i++)
  {
    AliLRCProcess *p = (dynamic_cast<AliLRCProcess*> (fLRCproc.At(i)));
    if(p) p->InitDataMembers();
    else continue;
  }

    // --------- Output list

  fOutList = new TList();

  // ---------- Adding data members to output list

   for(Int_t i=0; i < lLrcNum; i++)
  {
  fOutList->Add((dynamic_cast<AliLRCProcess*> (fLRCproc.At(i)))->CreateOutput());
  }

}

//________________________________________________________________________
void AliAnalysisTaskLRC::UserExec(Option_t *)
{
  // Main loop
  // Called for each event

   AliVEvent *event = InputEvent();

   if( fRunKine )
   {
   	AliMCEvent *eventMC =    MCEvent();
  	event = eventMC;
   }

  if (!event) {
     Printf("ERROR: Could not retrieve event");
     return;
  }

   Int_t lLrcNum=fLRCproc.GetEntries();

  //Track variables
  double lPt;   // Temp Pt
  double lEta;	  // Temp ETA

  for(Int_t i=0; i < lLrcNum; i++)
  {
    AliLRCProcess *prc = dynamic_cast<AliLRCProcess*> (fLRCproc.At(i));
    if(!prc) continue;
    else prc->StartEvent();
    //(dynamic_cast<AliLRCProcess*> (fLRCproc.At(i)))->StartEvent();
  }

    // Track loop
  for (Int_t iTracks = 0; iTracks < event->GetNumberOfTracks(); iTracks++) {
    AliVParticle* track = event->GetTrack(iTracks);
    if (!track) {
      Printf("ERROR: Could not receive track %d", iTracks);
      continue;
    }

    lPt=track->Pt();
    lEta=track->Eta();

    if(lPt<fMinPtLimit)continue;     // Dropping traks with lo Pt
    if(lPt>fMaxPtLimit)continue;     // Dropping traks with hi Pt

    if(fRunKine&&(track->Charge()*track->Charge()<0.5))continue; // Dropping neutral in Kine
    //if(fDropKineE&&fRunKine&&(track->PID()==AliPID::kElectron))continue; // Drop all e+- in Kine;

      for(Int_t i=0; i < lLrcNum; i++)
  {
    AliLRCProcess *p = (dynamic_cast<AliLRCProcess*> (fLRCproc.At(i)));
    if(p) p->AddTrackPtEta(lPt,lEta);
    else continue;
  }

  } //end of track loop

   for(Int_t i=0; i < lLrcNum; i++)
  {
  (dynamic_cast<AliLRCProcess*> (fLRCproc.At(i)))->FinishEvent();
  }

   // Post output data.

  PostData(1, fOutList);
}

//________________________________________________________________________
void AliAnalysisTaskLRC::Terminate(Option_t *)
{
  // Draw result to the screen
  // Called once at the end of the query
fOutList = dynamic_cast<TList*> (GetOutputData(0));

}

void AliAnalysisTaskLRC::AddLRCProcess(AliLRCProcess *newProc)
{
if(!newProc)
{Printf("ERROR:No AliLRCProcess object -  NULL pointer!");
return;
}
fLRCproc.Add(newProc);
return ;
}

<commit_msg>Coverity fixes<commit_after>// Analysis task for Long Range Correlation (LRC) analysis using TPC data
// This includes a TList of AliLRCProcess objects that are processing LRC analysis
// for a given Eta window
// This task is worcking with ESD data only

// Author : Andrey Ivanov , St.Peterburg State University
// Email: Andrey.Ivanov@cern.ch

// Version line : 3.5
// Version 3.5.5

#include "TChain.h"
#include "TTree.h"
#include "AliVEvent.h"
#include "AliMCEvent.h"
#include "AliAnalysisManager.h"
#include "AliAnalysisTaskLRC.h"
#include <AliPID.h>

ClassImp(AliAnalysisTaskLRC)

//________________________________________________________________________
AliAnalysisTaskLRC::AliAnalysisTaskLRC(const char *name,Bool_t runKine)
  : AliAnalysisTaskSE(name),fMaxPtLimit(5.0),fMinPtLimit(0.0),fDropKineE(kFALSE), fLRCproc(0),fOutList(0),fRunKine(0)
{
  //Init

  fRunKine=runKine;

  // Constructor

  // Output slot #1 writes into a TList container for all histogramms
  DefineOutput(1, TList::Class());

}

// ---------------------------------------  Setters ------------------

//________________________________________________________________________
void AliAnalysisTaskLRC::UserCreateOutputObjects()
{
  // Create histograms

  //LRC processors init
  Int_t lLrcNum=fLRCproc.GetEntries();

  for(Int_t i=0; i < lLrcNum; i++)
  {
    AliLRCProcess *p = (dynamic_cast<AliLRCProcess*> (fLRCproc.At(i)));
    if(p) p->InitDataMembers();
    else continue;
  }

    // --------- Output list

  fOutList = new TList();

  // ---------- Adding data members to output list

   for(Int_t i=0; i < lLrcNum; i++)
  {
    AliLRCProcess *p = (dynamic_cast<AliLRCProcess*> (fLRCproc.At(i)));
    if(p) fOutList->Add(p->CreateOutput());
    else continue;
  }

}

//________________________________________________________________________
void AliAnalysisTaskLRC::UserExec(Option_t *)
{
  // Main loop
  // Called for each event

   AliVEvent *event = InputEvent();

   if( fRunKine )
   {
   	AliMCEvent *eventMC =    MCEvent();
  	event = eventMC;
   }

  if (!event) {
     Printf("ERROR: Could not retrieve event");
     return;
  }

   Int_t lLrcNum=fLRCproc.GetEntries();

  //Track variables
  double lPt;   // Temp Pt
  double lEta;	  // Temp ETA

  for(Int_t i=0; i < lLrcNum; i++)
  {
    AliLRCProcess *prc = dynamic_cast<AliLRCProcess*> (fLRCproc.At(i));
    if(!prc) continue;
    else prc->StartEvent();
    //(dynamic_cast<AliLRCProcess*> (fLRCproc.At(i)))->StartEvent();
  }

    // Track loop
  for (Int_t iTracks = 0; iTracks < event->GetNumberOfTracks(); iTracks++) {
    AliVParticle* track = event->GetTrack(iTracks);
    if (!track) {
      Printf("ERROR: Could not receive track %d", iTracks);
      continue;
    }

    lPt=track->Pt();
    lEta=track->Eta();

    if(lPt<fMinPtLimit)continue;     // Dropping traks with lo Pt
    if(lPt>fMaxPtLimit)continue;     // Dropping traks with hi Pt

    if(fRunKine&&(track->Charge()*track->Charge()<0.5))continue; // Dropping neutral in Kine
    //if(fDropKineE&&fRunKine&&(track->PID()==AliPID::kElectron))continue; // Drop all e+- in Kine;

      for(Int_t i=0; i < lLrcNum; i++)
  {
    AliLRCProcess *p = (dynamic_cast<AliLRCProcess*> (fLRCproc.At(i)));
    if(p) p->AddTrackPtEta(lPt,lEta);
    else continue;
  }

  } //end of track loop

   for(Int_t i=0; i < lLrcNum; i++)
  {
    AliLRCProcess *p = (dynamic_cast<AliLRCProcess*> (fLRCproc.At(i)));
    if(p) p->FinishEvent();
    else continue;
  }

   // Post output data.

  PostData(1, fOutList);
}

//________________________________________________________________________
void AliAnalysisTaskLRC::Terminate(Option_t *)
{
  // Draw result to the screen
  // Called once at the end of the query
fOutList = dynamic_cast<TList*> (GetOutputData(0));

}

void AliAnalysisTaskLRC::AddLRCProcess(AliLRCProcess *newProc)
{
if(!newProc)
{Printf("ERROR:No AliLRCProcess object -  NULL pointer!");
return;
}
fLRCproc.Add(newProc);
return ;
}

<|endoftext|>


<commit_before>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

////////////////////////////////////////////////////////////////////////////////
//
//  This class contains all code which is used to compute any of the values
//  which can be of interest within a resonance analysis. Besides the obvious
//  invariant mass, it allows to compute other utility values on all possible
//  targets, in order to allow a wide spectrum of binning and checks.
//  When needed, this object can also define a binning in the variable which
//  it is required to compute, which is used for initializing axes of output
//  histograms (see AliRsnFunction).
//  The value computation requires this object to be passed the object whose
//  informations will be used. This object can be of any allowed input type
//  (track, pair, event), then this class must inherit from AliRsnTarget.
//  Then, when value computation is attempted, a check on target type is done
//  and computation is successful only if expected target matches that of the
//  passed object.
//  In some cases, the value computation can require a support external object,
//  which must then be passed to this class. It can be of any type inheriting
//  from TObject.
//
//  authors: A. Pulvirenti (alberto.pulvirenti@ct.infn.it)
//           M. Vala (martin.vala@cern.ch)
//  developers: F. Bellini (fbellini@cern.ch)
//
////////////////////////////////////////////////////////////////////////////////

#include "Riostream.h"

#include "AliLog.h"

#include "AliRsnMiniPair.h"
#include "AliRsnMiniEvent.h"
#include "AliRsnMiniParticle.h"

#include "AliRsnMiniValue.h"

ClassImp(AliRsnMiniValue)

//_____________________________________________________________________________
AliRsnMiniValue::AliRsnMiniValue(EType type, Bool_t useMC) :
   TNamed(ValueName(type, useMC), ""),
   fType(type),
   fUseMCInfo(useMC)
{
//
// Constructor
//
}

//_____________________________________________________________________________
AliRsnMiniValue::AliRsnMiniValue(const AliRsnMiniValue &copy) :
   TNamed(copy),
   fType(copy.fType),
   fUseMCInfo(copy.fUseMCInfo)
{
//
// Copy constructor
//
}

//_____________________________________________________________________________
AliRsnMiniValue &AliRsnMiniValue::operator=(const AliRsnMiniValue &copy)
{
//
// Assignment operator.
// Works like copy constructor.
//
   TNamed::operator=(copy);
   if (this == &copy)
      return *this;
   fType = copy.fType;
   fUseMCInfo = copy.fUseMCInfo;

   return (*this);
}

//_____________________________________________________________________________
const char *AliRsnMiniValue::TypeName(EType type)
{
//
// This method returns a string to give a name to each possible
// computation value.
//

   switch (type) {
      case kVz:           return "EventVz";
      case kSpherocity:   return "EventSpherocity";
      case kMult:         return "EventMult";
      case kRefMult:      return "EventReferenceMult";
      case kTracklets:    return "EventTracklets";
      case kPlaneAngle:   return "EventPlane";
      case kLeadingPt:    return "EventLeadingPt";
      case kPt:           return "Pt";
      case kPz:           return "Pz";
      case kInvMass:      return "InvMass";
      case kInvMassMother: return "InvMassMother";
      case kInvMassRes:   return "InvMassResolution";
      case kInvMassDiff:  return "InvMassDifference";
      case kEta:          return "Eta";
      case kMt:           return "Mt";
      case kY:            return "Y";
      case kPtRatio:      return "PtRatio";
      case kDipAngle:     return "DipAngle";
      case kCosThetaStar: return "CosThetaStar";
      case kCosThetaStarAbs:    return "CosThetaStarAbs";
      case kCosThetaJackson:    return "CosThetaJackson";
      case kCosThetaTransversity:    return "CosThetaTransversity";
      case kCosThetaHe:   return "CosThetaHe";
      case kCosThetaHeAbs:   return "CosThetaHeAbs";
      case kPhiHePbPb5:   return "PhiHePbPb5";
      case kPhiHePP5:   return "PhiHePP5";
      case kCosThetaToEventPlane:    return "CosThetaToEventPlane";
      case kAngleLeading: return "AngleToLeading";
      case kFirstDaughterPt: return "FirstDaughterPt";
      case kSecondDaughterPt: return "SecondDaughterPt";
      case kFirstDaughterP: return "FirstDaughterP";
      case kSecondDaughterP: return "SecondDaughterP";
      case kDCAproduct:   return "DaughterDCAproduct";
      case kFirstDaughterDCA: return "FirstDaughterDCA";
      case kSecondDaughterDCA: return "SecondDaughterDCA";
      case kNSisters:     return "NumberOfSisters";
      case kPairPtRes:        return "PairPtResolution";
      case kPairYRes:         return "PairYResolution";
      case kPhiV:         return "PhiV";
      case kAsym:         return "PairAsymmetry";
      default:            return "Undefined";
   }
}

//_____________________________________________________________________________
Float_t AliRsnMiniValue::Eval(AliRsnMiniPair *pair, AliRsnMiniEvent *event)
{
//
// Evaluation of the required value.
// In this implementation, fills the member 4-vectors with data
// coming from the object passed as argument, and then returns the value
//

   if (!pair && fType > kEventCuts) {
      AliError("Null pair passed!");
      return 1E20;
   }

   // compute value depending on types in the enumeration
   // if the type does not match any available choice, or if
   // the computation is not doable due to any problem
   // (not initialized support object, wrong values, risk of floating point errors)
   // the method returng kFALSE and sets the computed value to a meaningless number
   Double_t p3[3]= {0.,0.,0.};
   AliRsnMiniParticle *l;
   TLorentzVector v;
   switch (fType) {
         // ---- event values -------------------------------------------------------------------------
      case kVz:
         return event->Vz();
      case kSpherocity:
         return event->Spherocity();
      case kMult:
         return event->Mult();
      case kRefMult:
         return event->RefMult();
      case kTracklets:
         return event->Tracklets();
      case kPlaneAngle:
         return event->Angle();
      case kLeadingPt:
         l = event->LeadingParticle(fUseMCInfo);
         if (l) {
            l->Set4Vector(v,-1.0,fUseMCInfo);
            return v.Pt();
         }
         return 0.0;
      case kPt:
         return pair->Pt(fUseMCInfo);
      case kInvMass:
         return pair->InvMass(fUseMCInfo);
      case kInvMassMother:
         return pair->InvMass(kTRUE);
      case kEta:
         return pair->Eta(fUseMCInfo);
      case kInvMassRes:
         return pair->InvMassRes();
      case kInvMassDiff:
         return pair->InvMassDiff();
      case kMt:
         return pair->Mt(fUseMCInfo);
      case kY:
         return pair->Y(fUseMCInfo);
      case kPtRatio:
         return pair->PtRatio(fUseMCInfo);
      case kDipAngle:
         return pair->DipAngle(fUseMCInfo);
      case kCosThetaStar:
         return pair->CosThetaStar(fUseMCInfo);
      case kCosThetaStarAbs:
          return pair->CosThetaStarAbs(fUseMCInfo);
      case kCosThetaJackson:
         return pair->CosThetaJackson(fUseMCInfo);
      case kCosThetaTransversity:
         return pair->CosThetaTransversity(fUseMCInfo);
      case kCosThetaHe:
           return pair->CosThetaHe(fUseMCInfo);
      case kCosThetaHeAbs:
           return pair->CosThetaHeAbs(fUseMCInfo);
      case kPhiHePbPb5:
           return pair->PhiHePbPb5(fUseMCInfo);
      case kPhiHePP5:
           return pair->PhiHePP5(fUseMCInfo);
      case kCosThetaToEventPlane:
         return pair->CosThetaToEventPlane(event, fUseMCInfo);
      case kAngleLeading:
         l = event->LeadingParticle(fUseMCInfo);
         if (l) {
            l->Set4Vector(v,-1.0,fUseMCInfo);
            Double_t angle = v.Phi() - pair->Sum(fUseMCInfo).Phi();

            //return angle w.r.t. leading particle in the range -pi/2, 3/2pi
            while (angle >= 1.5 * TMath::Pi()) angle -= 2 * TMath::Pi();
            while (angle < -0.5 * TMath::Pi()) angle += 2 * TMath::Pi();
            return angle;
         }
//         AliWarning("This method is not yet implemented");
         return 1E20;
      case kFirstDaughterPt:
         return pair->DaughterPt(0,fUseMCInfo);
      case kSecondDaughterPt:
         return pair->DaughterPt(1,fUseMCInfo);
      case kFirstDaughterP:
         pair->DaughterPxPyPz(0,fUseMCInfo, p3);
         return TMath::Sqrt(p3[0]*p3[0]+p3[1]*p3[1]+p3[2]*p3[2]);
      case kSecondDaughterP:
         pair->DaughterPxPyPz(1,fUseMCInfo, p3);
         return TMath::Sqrt(p3[0]*p3[0]+p3[1]*p3[1]+p3[2]*p3[2]);
      case kDCAproduct:
         return pair->DCAProduct();
      case kFirstDaughterDCA:
         return pair->DaughterDCA(0);
      case kSecondDaughterDCA:
         return pair->DaughterDCA(1);
      case kNSisters:
         return pair->NSisters();
      case kPairPtRes:
         return pair->PairPtRes();
      case kPairYRes:
         return pair->PairYRes();
      case kPhiV:
         return pair->PhiV(fUseMCInfo);
      case kAsym:
         return pair->PairAsymmetry(fUseMCInfo);
      default:
         AliError("Invalid value type");
         return 1E20;
   }
}
<commit_msg>remove autocorrelation<commit_after>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

////////////////////////////////////////////////////////////////////////////////
//
//  This class contains all code which is used to compute any of the values
//  which can be of interest within a resonance analysis. Besides the obvious
//  invariant mass, it allows to compute other utility values on all possible
//  targets, in order to allow a wide spectrum of binning and checks.
//  When needed, this object can also define a binning in the variable which
//  it is required to compute, which is used for initializing axes of output
//  histograms (see AliRsnFunction).
//  The value computation requires this object to be passed the object whose
//  informations will be used. This object can be of any allowed input type
//  (track, pair, event), then this class must inherit from AliRsnTarget.
//  Then, when value computation is attempted, a check on target type is done
//  and computation is successful only if expected target matches that of the
//  passed object.
//  In some cases, the value computation can require a support external object,
//  which must then be passed to this class. It can be of any type inheriting
//  from TObject.
//
//  authors: A. Pulvirenti (alberto.pulvirenti@ct.infn.it)
//           M. Vala (martin.vala@cern.ch)
//  developers: F. Bellini (fbellini@cern.ch)
//
////////////////////////////////////////////////////////////////////////////////

#include "Riostream.h"

#include "AliLog.h"

#include "AliRsnMiniPair.h"
#include "AliRsnMiniEvent.h"
#include "AliRsnMiniParticle.h"

#include "AliRsnMiniValue.h"

ClassImp(AliRsnMiniValue)

//_____________________________________________________________________________
AliRsnMiniValue::AliRsnMiniValue(EType type, Bool_t useMC) :
   TNamed(ValueName(type, useMC), ""),
   fType(type),
   fUseMCInfo(useMC)
{
//
// Constructor
//
}

//_____________________________________________________________________________
AliRsnMiniValue::AliRsnMiniValue(const AliRsnMiniValue &copy) :
   TNamed(copy),
   fType(copy.fType),
   fUseMCInfo(copy.fUseMCInfo)
{
//
// Copy constructor
//
}

//_____________________________________________________________________________
AliRsnMiniValue &AliRsnMiniValue::operator=(const AliRsnMiniValue &copy)
{
//
// Assignment operator.
// Works like copy constructor.
//
   TNamed::operator=(copy);
   if (this == &copy)
      return *this;
   fType = copy.fType;
   fUseMCInfo = copy.fUseMCInfo;

   return (*this);
}

//_____________________________________________________________________________
const char *AliRsnMiniValue::TypeName(EType type)
{
//
// This method returns a string to give a name to each possible
// computation value.
//

   switch (type) {
      case kVz:           return "EventVz";
      case kSpherocity:   return "EventSpherocity";
      case kMult:         return "EventMult";
      case kRefMult:      return "EventReferenceMult";
      case kTracklets:    return "EventTracklets";
      case kPlaneAngle:   return "EventPlane";
      case kLeadingPt:    return "EventLeadingPt";
      case kPt:           return "Pt";
      case kPz:           return "Pz";
      case kInvMass:      return "InvMass";
      case kInvMassMother: return "InvMassMother";
      case kInvMassRes:   return "InvMassResolution";
      case kInvMassDiff:  return "InvMassDifference";
      case kEta:          return "Eta";
      case kMt:           return "Mt";
      case kY:            return "Y";
      case kPtRatio:      return "PtRatio";
      case kDipAngle:     return "DipAngle";
      case kCosThetaStar: return "CosThetaStar";
      case kCosThetaStarAbs:    return "CosThetaStarAbs";
      case kCosThetaJackson:    return "CosThetaJackson";
      case kCosThetaTransversity:    return "CosThetaTransversity";
      case kCosThetaHe:   return "CosThetaHe";
      case kCosThetaHeAbs:   return "CosThetaHeAbs";
      case kPhiHePbPb5:   return "PhiHePbPb5";
      case kPhiHePP5:   return "PhiHePP5";
      case kCosThetaToEventPlane:    return "CosThetaToEventPlane";
      case kAngleLeading: return "AngleToLeading";
      case kFirstDaughterPt: return "FirstDaughterPt";
      case kSecondDaughterPt: return "SecondDaughterPt";
      case kFirstDaughterP: return "FirstDaughterP";
      case kSecondDaughterP: return "SecondDaughterP";
      case kDCAproduct:   return "DaughterDCAproduct";
      case kFirstDaughterDCA: return "FirstDaughterDCA";
      case kSecondDaughterDCA: return "SecondDaughterDCA";
      case kNSisters:     return "NumberOfSisters";
      case kPairPtRes:        return "PairPtResolution";
      case kPairYRes:         return "PairYResolution";
      case kPhiV:         return "PhiV";
      case kAsym:         return "PairAsymmetry";
      default:            return "Undefined";
   }
}

//_____________________________________________________________________________
Float_t AliRsnMiniValue::Eval(AliRsnMiniPair *pair, AliRsnMiniEvent *event)
{
//
// Evaluation of the required value.
// In this implementation, fills the member 4-vectors with data
// coming from the object passed as argument, and then returns the value
//

   if (!pair && fType > kEventCuts) {
      AliError("Null pair passed!");
      return 1E20;
   }

   // compute value depending on types in the enumeration
   // if the type does not match any available choice, or if
   // the computation is not doable due to any problem
   // (not initialized support object, wrong values, risk of floating point errors)
   // the method returng kFALSE and sets the computed value to a meaningless number
   Double_t p3[3]= {0.,0.,0.};
   AliRsnMiniParticle *l;
   TLorentzVector v;
   switch (fType) {
         // ---- event values -------------------------------------------------------------------------
      case kVz:
         return event->Vz();
      case kSpherocity:
         return event->Spherocity();
      case kMult:
         return event->Mult();
      case kRefMult:
         return event->RefMult();
      case kTracklets:
         return event->Tracklets();
      case kPlaneAngle:
         return event->Angle();
      case kLeadingPt:
         l = event->LeadingParticle(fUseMCInfo);
         if (l) {
            l->Set4Vector(v,-1.0,fUseMCInfo);
            return v.Pt();
         }
         return 0.0;
      case kPt:
         return pair->Pt(fUseMCInfo);
      case kInvMass:
         return pair->InvMass(fUseMCInfo);
      case kInvMassMother:
         return pair->InvMass(kTRUE);
      case kEta:
         return pair->Eta(fUseMCInfo);
      case kInvMassRes:
         return pair->InvMassRes();
      case kInvMassDiff:
         return pair->InvMassDiff();
      case kMt:
         return pair->Mt(fUseMCInfo);
      case kY:
         return pair->Y(fUseMCInfo);
      case kPtRatio:
         return pair->PtRatio(fUseMCInfo);
      case kDipAngle:
         return pair->DipAngle(fUseMCInfo);
      case kCosThetaStar:
         return pair->CosThetaStar(fUseMCInfo);
      case kCosThetaStarAbs:
          return pair->CosThetaStarAbs(fUseMCInfo);
      case kCosThetaJackson:
         return pair->CosThetaJackson(fUseMCInfo);
      case kCosThetaTransversity:
         return pair->CosThetaTransversity(fUseMCInfo);
      case kCosThetaHe:
           return pair->CosThetaHe(fUseMCInfo);
      case kCosThetaHeAbs:
           return pair->CosThetaHeAbs(fUseMCInfo);
      case kPhiHePbPb5:
           return pair->PhiHePbPb5(fUseMCInfo);
      case kPhiHePP5:
           return pair->PhiHePP5(fUseMCInfo);
      case kCosThetaToEventPlane:
         return pair->CosThetaToEventPlane(event, fUseMCInfo);
      case kAngleLeading:
         l = event->LeadingParticle(fUseMCInfo);
         if (l) {
             if (pair->ContainsIndex(l->Index())) return 1E20;
            l->Set4Vector(v,-1.0,fUseMCInfo);
            Double_t angle = v.Phi() - pair->Sum(fUseMCInfo).Phi();

            //return angle w.r.t. leading particle in the range -pi/2, 3/2pi
            while (angle >= 1.5 * TMath::Pi()) angle -= 2 * TMath::Pi();
            while (angle < -0.5 * TMath::Pi()) angle += 2 * TMath::Pi();
            return angle;
         }
//         AliWarning("This method is not yet implemented");
         return 1E20;
      case kFirstDaughterPt:
         return pair->DaughterPt(0,fUseMCInfo);
      case kSecondDaughterPt:
         return pair->DaughterPt(1,fUseMCInfo);
      case kFirstDaughterP:
         pair->DaughterPxPyPz(0,fUseMCInfo, p3);
         return TMath::Sqrt(p3[0]*p3[0]+p3[1]*p3[1]+p3[2]*p3[2]);
      case kSecondDaughterP:
         pair->DaughterPxPyPz(1,fUseMCInfo, p3);
         return TMath::Sqrt(p3[0]*p3[0]+p3[1]*p3[1]+p3[2]*p3[2]);
      case kDCAproduct:
         return pair->DCAProduct();
      case kFirstDaughterDCA:
         return pair->DaughterDCA(0);
      case kSecondDaughterDCA:
         return pair->DaughterDCA(1);
      case kNSisters:
         return pair->NSisters();
      case kPairPtRes:
         return pair->PairPtRes();
      case kPairYRes:
         return pair->PairYRes();
      case kPhiV:
         return pair->PhiV(fUseMCInfo);
      case kAsym:
         return pair->PairAsymmetry(fUseMCInfo);
      default:
         AliError("Invalid value type");
         return 1E20;
   }
}
<|endoftext|>


<commit_before>/******************************************************************************
 * Copyright (c) 2013-2014, AllSeen Alliance. All rights reserved.
 *
 *    Permission to use, copy, modify, and/or distribute this software for any
 *    purpose with or without fee is hereby granted, provided that the above
 *    copyright notice and this permission notice appear in all copies.
 *
 *    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 *    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 *    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 *    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 *    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 *    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 *    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 ******************************************************************************/

#include <algorithm>
#include <qcc/Debug.h>
#include <alljoyn/about/AboutService.h>
#include <alljoyn/BusAttachment.h>

#define QCC_MODULE "ALLJOYN_ABOUT_SERVICE"
#define ABOUT_SERVICE_VERSION 1

using namespace ajn;
using namespace services;

static const char* ABOUT_INTERFACE_NAME = "org.alljoyn.About";

AboutService::AboutService(ajn::BusAttachment& bus, PropertyStore& store) :
    BusObject("/About"), m_BusAttachment(&bus), m_PropertyStore(&store),
    m_AnnounceSignalMember(NULL), m_AnnouncePort(0) {

    QCC_DbgTrace(("AboutService::%s", __FUNCTION__));
    std::vector<qcc::String> v;
    v.push_back(ABOUT_INTERFACE_NAME);
    m_AnnounceObjectsMap.insert(std::pair<qcc::String, std::vector<qcc::String> >("/About", v));
}

QStatus AboutService::Register(int port) {
    QCC_DbgTrace(("AboutService::%s", __FUNCTION__));
    QStatus status = ER_OK;

    m_AnnouncePort = port;
    InterfaceDescription* p_InterfaceDescription = const_cast<InterfaceDescription*>(m_BusAttachment->GetInterface(ABOUT_INTERFACE_NAME));
    if (!p_InterfaceDescription) {
        status = m_BusAttachment->CreateInterface(ABOUT_INTERFACE_NAME, p_InterfaceDescription, false);
        if (status != ER_OK) {
            return status;
        }

        if (!p_InterfaceDescription) {
            return ER_BUS_CANNOT_ADD_INTERFACE;
        }

        status = p_InterfaceDescription->AddMethod("GetAboutData", "s", "a{sv}", "languageTag,aboutData");
        if (status != ER_OK) {
            return status;
        }
        status = p_InterfaceDescription->AddMethod("GetObjectDescription", NULL, "a(oas)", "Control");
        if (status != ER_OK) {
            return status;
        }
        status = p_InterfaceDescription->AddSignal("Announce", "qqa(oas)a{sv}", "version,port,objectDescription,aboutData");
        if (status != ER_OK) {
            return status;
        }
        status = p_InterfaceDescription->AddProperty("Version", "q", (uint8_t) PROP_ACCESS_READ);
        if (status != ER_OK) {
            return status;
        }
        p_InterfaceDescription->Activate();
    }

    status = AddInterface(*p_InterfaceDescription);
    if (status == ER_OK) {
        status = AddMethodHandler(p_InterfaceDescription->GetMember("GetAboutData"),
                                  static_cast<MessageReceiver::MethodHandler>(&AboutService::GetAboutData));
        if (status != ER_OK) {
            return status;
        }
        status = AddMethodHandler(p_InterfaceDescription->GetMember("GetObjectDescription"),
                                  static_cast<MessageReceiver::MethodHandler>(&AboutService::GetObjectDescription));
        if (status != ER_OK) {
            return status;
        }

        m_AnnounceSignalMember = p_InterfaceDescription->GetMember("Announce");
        assert(m_AnnounceSignalMember);
    }

    return (status == ER_BUS_IFACE_ALREADY_EXISTS) ? ER_OK : status;
}

void AboutService::Unregister() {
    QCC_DbgTrace(("AboutService::%s", __FUNCTION__));
}

QStatus AboutService::AddObjectDescription(qcc::String const& path, std::vector<qcc::String> const& interfaceNames) {
    QCC_DbgTrace(("AboutService::%s", __FUNCTION__));
    QStatus status = ER_OK;
    std::map<qcc::String, std::vector<qcc::String> >::iterator it = m_AnnounceObjectsMap.find(path);
    if (it != m_AnnounceObjectsMap.end()) {
        it->second.insert(it->second.end(), interfaceNames.begin(), interfaceNames.end());
    } else {
        m_AnnounceObjectsMap.insert(std::pair<qcc::String, std::vector<qcc::String> >(path, interfaceNames));
    }
    return status;
}

QStatus AboutService::RemoveObjectDescription(qcc::String const& path, std::vector<qcc::String> const& interfaceNames) {
    QCC_DbgTrace(("AboutService::%s", __FUNCTION__));
    QStatus status = ER_OK;
    std::map<qcc::String, std::vector<qcc::String> >::iterator it = m_AnnounceObjectsMap.find(path);
    if (it != m_AnnounceObjectsMap.end()) {
        for (std::vector<qcc::String>::const_iterator itv = interfaceNames.begin(); itv != interfaceNames.end(); ++itv) {
            std::vector<qcc::String>::iterator findIterator = std::find(it->second.begin(), it->second.end(), itv->c_str());
            if (findIterator != it->second.end()) {
                it->second.erase(findIterator);
            }
        }
    }
    return status;
}

QStatus AboutService::Announce() {
    QCC_DbgTrace(("AboutService::%s", __FUNCTION__));
    QStatus status = ER_OK;
    if (m_AnnounceSignalMember == NULL) {
        return ER_FAIL;
    }
    MsgArg announceArgs[4];
    status = announceArgs[0].Set("q", ABOUT_SERVICE_VERSION);
    if (status != ER_OK) {
        return status;
    }
    status = announceArgs[1].Set("q", m_AnnouncePort);
    if (status != ER_OK) {
        return status;
    }
    std::vector<MsgArg> announceObjectsArg(m_AnnounceObjectsMap.size());
    int objIndex = 0;
    for (std::map<qcc::String, std::vector<qcc::String> >::const_iterator it = m_AnnounceObjectsMap.begin();
         it != m_AnnounceObjectsMap.end(); ++it) {

        qcc::String objectPath = it->first;
        std::vector<const char*> interfacesVector(it->second.size());
        std::vector<qcc::String>::const_iterator interfaceIt;
        int interfaceIndex = 0;

        for (interfaceIt = it->second.begin(); interfaceIt != it->second.end(); ++interfaceIt) {
            interfacesVector[interfaceIndex++] = interfaceIt->c_str();
        }

        status = announceObjectsArg[objIndex].Set("(oas)", objectPath.c_str(), interfacesVector.size(), (interfacesVector.empty()) ? NULL : &interfacesVector.front());
        if (status != ER_OK) {
            return status;
        }
        objIndex++;
    }
    status = announceArgs[2].Set("a(oas)", objIndex, (announceObjectsArg.empty()) ? NULL : &announceObjectsArg.front());
    if (status != ER_OK) {
        return status;
    }
    status = m_PropertyStore->ReadAll(NULL, PropertyStore::ANNOUNCE, announceArgs[3]);
    if (status != ER_OK) {
        return status;
    }
    Message msg(*m_BusAttachment);
    uint8_t flags = ALLJOYN_FLAG_SESSIONLESS;
#if !defined(NDEBUG)
    for (int i = 0; i < 4; i++) {
        QCC_DbgPrintf(("announceArgs[%d]=%s", i, announceArgs[i].ToString().c_str()));
    }
#endif
    status = Signal(NULL, 0, *m_AnnounceSignalMember, announceArgs, 4, (unsigned char) 0, flags);

    QCC_DbgPrintf(("Sent AnnounceSignal from %s  =%d", m_BusAttachment->GetUniqueName().c_str(), status));
    return status;

}

void AboutService::GetAboutData(const ajn::InterfaceDescription::Member* member, ajn::Message& msg) {
    QCC_DbgTrace(("AboutService::%s", __FUNCTION__));
    QStatus status = ER_OK;
    const ajn::MsgArg* args = 0;
    size_t numArgs = 0;
    msg->GetArgs(numArgs, args);
    if (numArgs == 1) {
        ajn::MsgArg retargs[1];
        status = m_PropertyStore->ReadAll(args[0].v_string.str, PropertyStore::READ, retargs[0]);
        QCC_DbgPrintf(("m_pPropertyStore->ReadAll(%s,PropertyStore::READ)  =%s", args[0].v_string.str, QCC_StatusText(status)));
        if (status != ER_OK) {
            if (status == ER_LANGUAGE_NOT_SUPPORTED) {
                MethodReply(msg, "org.alljoyn.Error.LanguageNotSupported", "The language specified is not supported");
                return;
            }
            MethodReply(msg, status);
            return;
        } else {
            MethodReply(msg, retargs, 1);
        }
    } else {
        MethodReply(msg, ER_INVALID_DATA);
    }
}

void AboutService::GetObjectDescription(const ajn::InterfaceDescription::Member* member, ajn::Message& msg) {
    QCC_DbgTrace(("AboutService::%s", __FUNCTION__));
    const ajn::MsgArg* args = 0;
    size_t numArgs = 0;
    msg->GetArgs(numArgs, args);
    if (numArgs == 0) {
        ajn::MsgArg retargs[1];
        std::vector<MsgArg> objectArg(m_AnnounceObjectsMap.size());
        int objIndex = 0;
        for (std::map<qcc::String, std::vector<qcc::String> >::const_iterator it = m_AnnounceObjectsMap.begin();
             it != m_AnnounceObjectsMap.end(); ++it) {
            const qcc::String& key = it->first;
            std::vector<const char*> interfacesVec(it->second.size());
            std::vector<qcc::String>::const_iterator interfaceIt;
            int interfaceIndex = 0;

            for (interfaceIt = it->second.begin(); interfaceIt != it->second.end(); ++interfaceIt) {
                interfacesVec[interfaceIndex] = interfaceIt->c_str();
            }

            objectArg[objIndex].Set("(oas)", key.c_str(), interfacesVec.size(), (interfacesVec.empty()) ? NULL : &interfacesVec.front());
            objIndex++;
        }
        retargs[0].Set("a(oas)", objectArg.size(), (objectArg.empty()) ? NULL : &objectArg.front());
        MethodReply(msg, retargs, 1);
    } else {
        MethodReply(msg, ER_INVALID_DATA);
    }
}

QStatus AboutService::Get(const char*ifcName, const char*propName, MsgArg& val) {
    QCC_DbgTrace(("AboutService::%s", __FUNCTION__));
    QStatus status = ER_BUS_NO_SUCH_PROPERTY;
    if (0 == strcmp(ifcName, ABOUT_INTERFACE_NAME)) {
        if (0 == strcmp("Version", propName)) {
            status = val.Set("q", ABOUT_SERVICE_VERSION);
        }
    }
    return status;
}
<commit_msg>ASACORE-293 Fixed call to org.alljoyn.About.GetObjectDescription<commit_after>/******************************************************************************
 * Copyright (c) 2013-2014, AllSeen Alliance. All rights reserved.
 *
 *    Permission to use, copy, modify, and/or distribute this software for any
 *    purpose with or without fee is hereby granted, provided that the above
 *    copyright notice and this permission notice appear in all copies.
 *
 *    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 *    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 *    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 *    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 *    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 *    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 *    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 ******************************************************************************/

#include <algorithm>
#include <qcc/Debug.h>
#include <alljoyn/about/AboutService.h>
#include <alljoyn/BusAttachment.h>

#define QCC_MODULE "ALLJOYN_ABOUT_SERVICE"
#define ABOUT_SERVICE_VERSION 1

using namespace ajn;
using namespace services;

static const char* ABOUT_INTERFACE_NAME = "org.alljoyn.About";

AboutService::AboutService(ajn::BusAttachment& bus, PropertyStore& store) :
    BusObject("/About"), m_BusAttachment(&bus), m_PropertyStore(&store),
    m_AnnounceSignalMember(NULL), m_AnnouncePort(0) {

    QCC_DbgTrace(("AboutService::%s", __FUNCTION__));
    std::vector<qcc::String> v;
    v.push_back(ABOUT_INTERFACE_NAME);
    m_AnnounceObjectsMap.insert(std::pair<qcc::String, std::vector<qcc::String> >("/About", v));
}

QStatus AboutService::Register(int port) {
    QCC_DbgTrace(("AboutService::%s", __FUNCTION__));
    QStatus status = ER_OK;

    m_AnnouncePort = port;
    InterfaceDescription* p_InterfaceDescription = const_cast<InterfaceDescription*>(m_BusAttachment->GetInterface(ABOUT_INTERFACE_NAME));
    if (!p_InterfaceDescription) {
        status = m_BusAttachment->CreateInterface(ABOUT_INTERFACE_NAME, p_InterfaceDescription, false);
        if (status != ER_OK) {
            return status;
        }

        if (!p_InterfaceDescription) {
            return ER_BUS_CANNOT_ADD_INTERFACE;
        }

        status = p_InterfaceDescription->AddMethod("GetAboutData", "s", "a{sv}", "languageTag,aboutData");
        if (status != ER_OK) {
            return status;
        }
        status = p_InterfaceDescription->AddMethod("GetObjectDescription", NULL, "a(oas)", "Control");
        if (status != ER_OK) {
            return status;
        }
        status = p_InterfaceDescription->AddSignal("Announce", "qqa(oas)a{sv}", "version,port,objectDescription,aboutData");
        if (status != ER_OK) {
            return status;
        }
        status = p_InterfaceDescription->AddProperty("Version", "q", (uint8_t) PROP_ACCESS_READ);
        if (status != ER_OK) {
            return status;
        }
        p_InterfaceDescription->Activate();
    }

    status = AddInterface(*p_InterfaceDescription);
    if (status == ER_OK) {
        status = AddMethodHandler(p_InterfaceDescription->GetMember("GetAboutData"),
                                  static_cast<MessageReceiver::MethodHandler>(&AboutService::GetAboutData));
        if (status != ER_OK) {
            return status;
        }
        status = AddMethodHandler(p_InterfaceDescription->GetMember("GetObjectDescription"),
                                  static_cast<MessageReceiver::MethodHandler>(&AboutService::GetObjectDescription));
        if (status != ER_OK) {
            return status;
        }

        m_AnnounceSignalMember = p_InterfaceDescription->GetMember("Announce");
        assert(m_AnnounceSignalMember);
    }

    return (status == ER_BUS_IFACE_ALREADY_EXISTS) ? ER_OK : status;
}

void AboutService::Unregister() {
    QCC_DbgTrace(("AboutService::%s", __FUNCTION__));
}

QStatus AboutService::AddObjectDescription(qcc::String const& path, std::vector<qcc::String> const& interfaceNames) {
    QCC_DbgTrace(("AboutService::%s", __FUNCTION__));
    QStatus status = ER_OK;
    std::map<qcc::String, std::vector<qcc::String> >::iterator it = m_AnnounceObjectsMap.find(path);
    if (it != m_AnnounceObjectsMap.end()) {
        it->second.insert(it->second.end(), interfaceNames.begin(), interfaceNames.end());
    } else {
        m_AnnounceObjectsMap.insert(std::pair<qcc::String, std::vector<qcc::String> >(path, interfaceNames));
    }
    return status;
}

QStatus AboutService::RemoveObjectDescription(qcc::String const& path, std::vector<qcc::String> const& interfaceNames) {
    QCC_DbgTrace(("AboutService::%s", __FUNCTION__));
    QStatus status = ER_OK;
    std::map<qcc::String, std::vector<qcc::String> >::iterator it = m_AnnounceObjectsMap.find(path);
    if (it != m_AnnounceObjectsMap.end()) {
        for (std::vector<qcc::String>::const_iterator itv = interfaceNames.begin(); itv != interfaceNames.end(); ++itv) {
            std::vector<qcc::String>::iterator findIterator = std::find(it->second.begin(), it->second.end(), itv->c_str());
            if (findIterator != it->second.end()) {
                it->second.erase(findIterator);
            }
        }
    }
    return status;
}

QStatus AboutService::Announce() {
    QCC_DbgTrace(("AboutService::%s", __FUNCTION__));
    QStatus status = ER_OK;
    if (m_AnnounceSignalMember == NULL) {
        return ER_FAIL;
    }
    MsgArg announceArgs[4];
    status = announceArgs[0].Set("q", ABOUT_SERVICE_VERSION);
    if (status != ER_OK) {
        return status;
    }
    status = announceArgs[1].Set("q", m_AnnouncePort);
    if (status != ER_OK) {
        return status;
    }
    std::vector<MsgArg> announceObjectsArg(m_AnnounceObjectsMap.size());
    int objIndex = 0;
    for (std::map<qcc::String, std::vector<qcc::String> >::const_iterator it = m_AnnounceObjectsMap.begin();
         it != m_AnnounceObjectsMap.end(); ++it) {

        qcc::String objectPath = it->first;
        std::vector<const char*> interfacesVector(it->second.size());
        std::vector<qcc::String>::const_iterator interfaceIt;
        int interfaceIndex = 0;

        for (interfaceIt = it->second.begin(); interfaceIt != it->second.end(); ++interfaceIt) {
            interfacesVector[interfaceIndex++] = interfaceIt->c_str();
        }

        status = announceObjectsArg[objIndex].Set("(oas)", objectPath.c_str(), interfacesVector.size(), (interfacesVector.empty()) ? NULL : &interfacesVector.front());
        if (status != ER_OK) {
            return status;
        }
        objIndex++;
    }
    status = announceArgs[2].Set("a(oas)", objIndex, (announceObjectsArg.empty()) ? NULL : &announceObjectsArg.front());
    if (status != ER_OK) {
        return status;
    }
    status = m_PropertyStore->ReadAll(NULL, PropertyStore::ANNOUNCE, announceArgs[3]);
    if (status != ER_OK) {
        return status;
    }
    Message msg(*m_BusAttachment);
    uint8_t flags = ALLJOYN_FLAG_SESSIONLESS;
#if !defined(NDEBUG)
    for (int i = 0; i < 4; i++) {
        QCC_DbgPrintf(("announceArgs[%d]=%s", i, announceArgs[i].ToString().c_str()));
    }
#endif
    status = Signal(NULL, 0, *m_AnnounceSignalMember, announceArgs, 4, (unsigned char) 0, flags);

    QCC_DbgPrintf(("Sent AnnounceSignal from %s  =%d", m_BusAttachment->GetUniqueName().c_str(), status));
    return status;

}

void AboutService::GetAboutData(const ajn::InterfaceDescription::Member* member, ajn::Message& msg) {
    QCC_DbgTrace(("AboutService::%s", __FUNCTION__));
    QStatus status = ER_OK;
    const ajn::MsgArg* args = 0;
    size_t numArgs = 0;
    msg->GetArgs(numArgs, args);
    if (numArgs == 1) {
        ajn::MsgArg retargs[1];
        status = m_PropertyStore->ReadAll(args[0].v_string.str, PropertyStore::READ, retargs[0]);
        QCC_DbgPrintf(("m_pPropertyStore->ReadAll(%s,PropertyStore::READ)  =%s", args[0].v_string.str, QCC_StatusText(status)));
        if (status != ER_OK) {
            if (status == ER_LANGUAGE_NOT_SUPPORTED) {
                MethodReply(msg, "org.alljoyn.Error.LanguageNotSupported", "The language specified is not supported");
                return;
            }
            MethodReply(msg, status);
            return;
        } else {
            MethodReply(msg, retargs, 1);
        }
    } else {
        MethodReply(msg, ER_INVALID_DATA);
    }
}

void AboutService::GetObjectDescription(const ajn::InterfaceDescription::Member* member, ajn::Message& msg) {
    QCC_DbgTrace(("AboutService::%s", __FUNCTION__));
    const ajn::MsgArg* args = 0;
    size_t numArgs = 0;
    msg->GetArgs(numArgs, args);
    if (numArgs == 0) {
        ajn::MsgArg retargs[1];
        std::vector<MsgArg> objectArg(m_AnnounceObjectsMap.size());
        int objIndex = 0;
        for (std::map<qcc::String, std::vector<qcc::String> >::const_iterator it = m_AnnounceObjectsMap.begin();
             it != m_AnnounceObjectsMap.end(); ++it) {
            const qcc::String& key = it->first;
            std::vector<const char*> interfacesVec(it->second.size());
            std::vector<qcc::String>::const_iterator interfaceIt;
            int interfaceIndex = 0;

            for (interfaceIt = it->second.begin(); interfaceIt != it->second.end(); ++interfaceIt) {
                interfacesVec[interfaceIndex++] = interfaceIt->c_str();
            }

            objectArg[objIndex].Set("(oas)", key.c_str(), interfacesVec.size(), (interfacesVec.empty()) ? NULL : &interfacesVec.front());
            objIndex++;
        }
        retargs[0].Set("a(oas)", objectArg.size(), (objectArg.empty()) ? NULL : &objectArg.front());
        MethodReply(msg, retargs, 1);
    } else {
        MethodReply(msg, ER_INVALID_DATA);
    }
}

QStatus AboutService::Get(const char*ifcName, const char*propName, MsgArg& val) {
    QCC_DbgTrace(("AboutService::%s", __FUNCTION__));
    QStatus status = ER_BUS_NO_SUCH_PROPERTY;
    if (0 == strcmp(ifcName, ABOUT_INTERFACE_NAME)) {
        if (0 == strcmp("Version", propName)) {
            status = val.Set("q", ABOUT_SERVICE_VERSION);
        }
    }
    return status;
}
<|endoftext|>


<commit_before>#include "plant_printer.h"

#include <algorithm>
#include <iostream>

#include "asdf_multiplat/main/asdf_defs.h"
#include "asdf_multiplat/utilities/utilities.h"

using namespace std;
using namespace plantgen;
using namespace asdf::util;

namespace plant_printer
{
    namespace
    {
        constexpr char string_var_delimiter = '%';
    }

    string_var_locations_t parse_print_string(string const& print_string)
    {
        string_var_locations_t var_locations;

        size_t pos = 0;
        size_t endpos = 0;

        while(true)
        {
            pos = print_string.find(string_var_delimiter, endpos);
            if(pos == string::npos)
                break;

            endpos = print_string.find(string_var_delimiter, pos+1);

            if(endpos == string::npos)
            {
                EXPLODE("unmached %%");
            }

            ASSERT(endpos > pos, "");
            ASSERT(endpos-pos >= 1, "");
            std::string key = print_string.substr(pos+1, endpos-pos-1);
            var_locations.insert({key,pos});

            endpos++; //move it past the percent sign for the next find call
        }

        return var_locations;
    }

    struct sorted_range_value_t
    {
        int percentage;
        std::string range_string;
    };

    std::vector<sorted_range_value_t> get_sorted_range(generated_node_t const& node)
    {
        if(node.generated_values.size() == 0)
            return std::vector<sorted_range_value_t>();

        //ASSERT(node.generated_values.size() > 0, "expected some flavors to sort");
        std::vector<sorted_range_value_t> sorted_values;
        sorted_values.reserve(node.generated_values.size());

        for(auto const& val : node.generated_values)
        {
            auto percent_sign_pos = val.find('%');

            ASSERT(percent_sign_pos != std::string::npos, "");
            if(percent_sign_pos != std::string::npos)
            {
                sorted_range_value_t sv =
                {
                    stoi(val.substr(0, percent_sign_pos)),
                    val.substr(percent_sign_pos + 2)
                };

                sorted_values.push_back(sv);
            }
        }

        std::sort(sorted_values.begin(), sorted_values.end(),
            [](sorted_range_value_t const& lhs, sorted_range_value_t const& rhs)
            {
                return lhs.percentage > rhs.percentage;
            });

        return sorted_values;
    }

    string print_range_value(generated_node_t const& range)
    {
        auto sorted_values = get_sorted_range(range);

        ASSERT(sorted_values.size() > 0, "");

        size_t div = 100 / sorted_values.size();

        int largest_diff = 0;
        for(auto const& sorted : sorted_values)
        {
            int diff = sorted.percentage - sorted_values[0].percentage;
            largest_diff = std::max(abs(diff), largest_diff);
        }

        if(largest_diff <= 4)
        {
            vector<string> strs;
            strs.reserve(sorted_values.size());
            for(auto const& sorted : sorted_values)
            {
                strs.push_back(sorted.range_string);
            }

            return "equal parts " + combine_strings_with_comma_and(strs);
        }
        else if(sorted_values[0].percentage >= 95)
        {
            return "completely " + sorted_values[0].range_string;
        }
        else if(sorted_values[0].percentage >= 90)
        {
            return "very " + sorted_values[0].range_string;
        }
        else if(sorted_values[0].percentage >= 70)
        {
            std::string ret = "mostly " + sorted_values[0].range_string;

            if(sorted_values.size() >= 2 && sorted_values[1].percentage > 20)
            {
                ret += " and slightly " + sorted_values[1].range_string;
            }

            return ret;
        }
        else
        {
            std::string ret = "somewhat " + sorted_values[0].range_string;

            if(sorted_values.size() >= 2 && sorted_values[1].percentage > 20)
            {
                ret += " and slightly " + sorted_values[1].range_string;
            }

            return ret;
        }
    }

    string print_multi_value(generated_node_t const& node)
    {
        if(node.generated_values.empty())
            return "";

        string property_string;// =  node.name + " that is ";

        if(node.generated_values.size() == 1)
            return node.generated_values[0];

        property_string += combine_strings_with_comma_and(node.generated_values);

        return property_string;
    }

    string print_basic_property(generated_node_t const& node)
    {
        ASSERT(node.children.empty(), "");

        if(node.generated_values.size() == 1)
        {
            return node.generated_values[0];
        }
        else if(node.generated_values.size() > 1)
        {
            // if there is a % in the first few characters
            // (ie: if its XXX% or XX% or X%)
            if(node.generated_values[0].find('%') <= 3)
            {
                return print_range_value(node);
            }
            else
            {
                return print_multi_value(node);
            }
        }

        return "";
    }

    string print_sub_property(generated_node_t const& node, size_t level, print_flags_t print_flags)
    {
        std::string summary = indenation_string(level);

        if(node.print_string.size() > 0)
        {
            summary += print_property_with_string(node);
        }
        else
        {
            //if not flagged to skip the name, print it
            if((print_flags & print_flags_skip_name) == 0)
                summary += node.name_string() + ": ";

            if(node.children.empty() && node.value_nodes.empty())
            {
                summary += print_basic_property(node);
            }
            else
            {
                //change trailing space to a newline if we are printing a sub-property of node
                if(summary.size() > 0 && summary.back() == ' ')
                    summary.back() = '\n';

                for(auto const& child : node.children)
                    summary += print_sub_property(child, level + 1) + "\n";
                for(auto const& vn : node.value_nodes)
                    summary += print_sub_property(vn, level + 1) + "\n";

                summary.resize(summary.size() - 1);
            }
        }

        return summary;
    }

    /// TODO: move to util file
    /// https://stackoverflow.com/a/5056797
    template<typename A, typename B>
    std::pair<B,A> flip_pair(const std::pair<A,B> &p)
    {
        return std::pair<B,A>(p.second, p.first);
    }

    template<typename A, typename B>
    std::multimap<B,A> flip_map(const std::map<A,B> &src)
    {
        std::multimap<B,A> dst;
        std::transform(src.begin(), src.end(), std::inserter(dst, dst.begin()),
                       flip_pair<A,B>);
        return dst;
    }
    ///

    string print_property_with_string(generated_node_t const& node)
    {
        WARN_IF(node.print_string.empty(), "node has no print string in a function that is based around having one");
        return print_property_with_string(node, node.print_string);
    }

    string print_property_with_string(generated_node_t const& node, string const& print_string)
    {
        if(print_string.empty())
            return "";

        std::string final_string = print_string;

        // sort locations by string position (earliest to latest)
        // so that I can adjust the string replacement positions
        // as the string changes size
        auto var_locations = parse_print_string(print_string);
        auto sorted_locs = flip_map(var_locations);
        int adjust = 0;

        for(auto const& var_loc : sorted_locs)
        {
            std::string var_str;
            auto prev_size = final_string.size();

            if(var_loc.second == "Name")
            {
                final_string.replace(var_loc.first + adjust, 4+2, node.name);
            }
            else
            {
                for(generated_node_t const& child : node.children)
                {
                    if(var_loc.second == child.name)
                    {
                        string str = print_sub_property(child, 0, print_flags_skip_name);
                        final_string.replace(var_loc.first + adjust, var_loc.second.size()+2, str);
                        break;
                    }
                }
            }

            adjust += int(final_string.size()) - int(prev_size);
        }

        return final_string;
    }

    string print_plant(generated_node_t const& plant_node)
    {
        return "This " + plant_node.name + " " + print_sub_property(plant_node);
    }
}<commit_msg>more refinement of print_range_value()<commit_after>#include "plant_printer.h"

#include <algorithm>
#include <iostream>

#include "asdf_multiplat/main/asdf_defs.h"
#include "asdf_multiplat/utilities/utilities.h"

using namespace std;
using namespace plantgen;
using namespace asdf::util;

namespace plant_printer
{
    namespace
    {
        constexpr char string_var_delimiter = '%';
    }

    string_var_locations_t parse_print_string(string const& print_string)
    {
        string_var_locations_t var_locations;

        size_t pos = 0;
        size_t endpos = 0;

        while(true)
        {
            pos = print_string.find(string_var_delimiter, endpos);
            if(pos == string::npos)
                break;

            endpos = print_string.find(string_var_delimiter, pos+1);

            if(endpos == string::npos)
            {
                EXPLODE("unmached %%");
            }

            ASSERT(endpos > pos, "");
            ASSERT(endpos-pos >= 1, "");
            std::string key = print_string.substr(pos+1, endpos-pos-1);
            var_locations.insert({key,pos});

            endpos++; //move it past the percent sign for the next find call
        }

        return var_locations;
    }

    struct sorted_range_value_t
    {
        int percentage;
        std::string range_string;
    };

    std::vector<sorted_range_value_t> get_sorted_range(generated_node_t const& node)
    {
        if(node.generated_values.size() == 0)
            return std::vector<sorted_range_value_t>();

        //ASSERT(node.generated_values.size() > 0, "expected some flavors to sort");
        std::vector<sorted_range_value_t> sorted_values;
        sorted_values.reserve(node.generated_values.size());

        for(auto const& val : node.generated_values)
        {
            auto percent_sign_pos = val.find('%');

            ASSERT(percent_sign_pos != std::string::npos, "");
            if(percent_sign_pos != std::string::npos)
            {
                sorted_range_value_t sv =
                {
                    stoi(val.substr(0, percent_sign_pos)),
                    val.substr(percent_sign_pos + 2)
                };

                sorted_values.push_back(sv);
            }
        }

        std::sort(sorted_values.begin(), sorted_values.end(),
            [](sorted_range_value_t const& lhs, sorted_range_value_t const& rhs)
            {
                // return true if the left should be ordered before the second
                return lhs.percentage > rhs.percentage;
            });

        return sorted_values;
    }

    string print_range_value(generated_node_t const& range)
    {
        auto sorted_values = get_sorted_range(range);

        ASSERT(sorted_values.size() > 0, "");

        if(sorted_values.size() == 1)
        {
            return sorted_values[0].range_string;
        }

        size_t div = 100 / sorted_values.size();
        int largest_diff = 0;
        for(auto const& sorted : sorted_values)
        {
            int diff = sorted.percentage - sorted_values[0].percentage;
            largest_diff = std::max(abs(diff), largest_diff);
        }

        if(largest_diff <= 4)
        {
            vector<string> strs;
            strs.reserve(sorted_values.size());
            for(auto const& sorted : sorted_values)
            {
                strs.push_back(sorted.range_string);
            }

            return "equal parts " + combine_strings_with_comma_and(strs);
        }
        else if(sorted_values[0].percentage >= 95)
        {
            return "completely " + sorted_values[0].range_string;
        }
        else if(sorted_values[0].percentage >= 90)
        {
            return "very " + sorted_values[0].range_string;
        }
        else if(sorted_values[0].percentage >= 70)
        {
            std::string ret = "mostly " + sorted_values[0].range_string;

            if(sorted_values.size() >= 2 && sorted_values[1].percentage > 20)
            {
                ret += " and slightly " + sorted_values[1].range_string;
            }

            return ret;
        }
        else if(sorted_values[0].percentage >= 45
            && (sorted_values.size() > 0 && sorted_values[1].percentage > 30))
        {
            return sorted_values[0].range_string + " and " + sorted_values[1].range_string;
        }
        else
        {
            std::string ret = "somewhat " + sorted_values[0].range_string;

            if(sorted_values.size() >= 2 && sorted_values[1].percentage > 20)
            {
                ret += " and slightly " + sorted_values[1].range_string;
            }

            return ret;
        }
    }

    string print_multi_value(generated_node_t const& node)
    {
        if(node.generated_values.empty())
            return "";

        string property_string;// =  node.name + " that is ";

        if(node.generated_values.size() == 1)
            return node.generated_values[0];

        property_string += combine_strings_with_comma_and(node.generated_values);

        return property_string;
    }

    string print_basic_property(generated_node_t const& node)
    {
        ASSERT(node.children.empty(), "");

        if(node.generated_values.size() == 1)
        {
            return node.generated_values[0];
        }
        else if(node.generated_values.size() > 1)
        {
            // if there is a % in the first few characters
            // (ie: if its XXX% or XX% or X%)
            if(node.generated_values[0].find('%') <= 3)
            {
                return print_range_value(node);
            }
            else
            {
                return print_multi_value(node);
            }
        }

        return "";
    }

    string print_sub_property(generated_node_t const& node, size_t level, print_flags_t print_flags)
    {
        std::string summary = indenation_string(level);

        if(node.print_string.size() > 0)
        {
            summary += print_property_with_string(node);
        }
        else
        {
            //if not flagged to skip the name, print it
            if((print_flags & print_flags_skip_name) == 0)
                summary += node.name_string() + ": ";

            if(node.children.empty() && node.value_nodes.empty())
            {
                summary += print_basic_property(node);
            }
            else
            {
                //change trailing space to a newline if we are printing a sub-property of node
                if(summary.size() > 0 && summary.back() == ' ')
                    summary.back() = '\n';

                for(auto const& child : node.children)
                    summary += print_sub_property(child, level + 1) + "\n";
                for(auto const& vn : node.value_nodes)
                    summary += print_sub_property(vn, level + 1) + "\n";

                summary.resize(summary.size() - 1);
            }
        }

        return summary;
    }

    /// TODO: move to util file
    /// https://stackoverflow.com/a/5056797
    template<typename A, typename B>
    std::pair<B,A> flip_pair(const std::pair<A,B> &p)
    {
        return std::pair<B,A>(p.second, p.first);
    }

    template<typename A, typename B>
    std::multimap<B,A> flip_map(const std::map<A,B> &src)
    {
        std::multimap<B,A> dst;
        std::transform(src.begin(), src.end(), std::inserter(dst, dst.begin()),
                       flip_pair<A,B>);
        return dst;
    }
    ///

    string print_property_with_string(generated_node_t const& node)
    {
        WARN_IF(node.print_string.empty(), "node has no print string in a function that is based around having one");
        return print_property_with_string(node, node.print_string);
    }

    string print_property_with_string(generated_node_t const& node, string const& print_string)
    {
        if(print_string.empty())
            return "";

        std::string final_string = print_string;

        // sort locations by string position (earliest to latest)
        // so that I can adjust the string replacement positions
        // as the string changes size
        auto var_locations = parse_print_string(print_string);
        auto sorted_locs = flip_map(var_locations);
        int adjust = 0;

        for(auto const& var_loc : sorted_locs)
        {
            std::string var_str;
            auto prev_size = final_string.size();

            if(var_loc.second == "Name")
            {
                final_string.replace(var_loc.first + adjust, 4+2, node.name);
            }
            else
            {
                for(generated_node_t const& child : node.children)
                {
                    if(var_loc.second == child.name)
                    {
                        string str = print_sub_property(child, 0, print_flags_skip_name);
                        final_string.replace(var_loc.first + adjust, var_loc.second.size()+2, str);
                        break;
                    }
                }
            }

            adjust += int(final_string.size()) - int(prev_size);
        }

        return final_string;
    }

    string print_plant(generated_node_t const& plant_node)
    {
        return "This " + plant_node.name + " " + print_sub_property(plant_node);
    }
}<|endoftext|>


<commit_before>/*=========================================================================
 *
 *  Copyright Insight Software Consortium
 *
 *  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.txt
 *
 *  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.
 *
 *=========================================================================*/

#include "itkModifiedButterflyTriangleCellSubdivisionQuadEdgeMeshFilter.h"
#include "itkLinearTriangleCellSubdivisionQuadEdgeMeshFilter.h"
#include "itkLoopTriangleCellSubdivisionQuadEdgeMeshFilter.h"
#include "itkSquareThreeTriangleCellSubdivisionQuadEdgeMeshFilter.h"
#include "itkIterativeTriangleCellSubdivisionQuadEdgeMeshFilter.h"
#include "itkQuadEdgeMesh.h"
#include "itkQuadEdgeMeshParamMatrixCoefficients.h"
#include "itkSmoothingQuadEdgeMeshFilter.h"
#include "itkMeshFileReader.h"
#include "itkMeshFileWriter.h"

template< typename TTriangleCellSubdivisionFilter >
int TriangleCellSubdivisionQuadEdgeMeshFilterTest( int argc, char *argv[] )
{

  typedef TTriangleCellSubdivisionFilter                         TriangleCellSubdivisionFilterType;
  typedef typename TriangleCellSubdivisionFilterType::Pointer    TriangleCellSubdivisionFilterPointer;

  typedef typename TriangleCellSubdivisionFilterType::InputMeshType    InputMeshType;
  typedef typename TriangleCellSubdivisionFilterType::OutputMeshType   OutputMeshType;

  typedef itk::IterativeTriangleCellSubdivisionQuadEdgeMeshFilter< InputMeshType, TriangleCellSubdivisionFilterType > IterativeTriangleCellSubdivisionFilterType;
  typedef typename IterativeTriangleCellSubdivisionFilterType::Pointer                                                IterativeTriangleCellSubdivisionFilterPointer;

  typedef itk::MeshFileReader< InputMeshType >  ReaderType;
  typedef itk::MeshFileWriter< OutputMeshType > WriterType;

  typename ReaderType::Pointer reader = ReaderType::New();
  reader->SetFileName( argv[1] );
  try
    {
    reader->Update();
    }
  catch ( itk::ExceptionObject & exp )
    {
    std::cerr << "Exception thrown while reading the input file " << std::endl;
    std::cerr << exp << std::endl;
    return EXIT_FAILURE;
    }

  IterativeTriangleCellSubdivisionFilterPointer subdivision = IterativeTriangleCellSubdivisionFilterType::New();

  if ( argc >= 5 )
    {
    unsigned int n = std::atoi(argv[4]);
    subdivision->SetResolutionLevels(n);
    }

  if ( argc >= 6 )
    {
    int type = std::atoi(argv[5]);
    if ( type )
      {
      typename IterativeTriangleCellSubdivisionFilterType::SubdivisionCellContainer cellsToBeSubdivided;

      cellsToBeSubdivided.push_back(0);
      cellsToBeSubdivided.push_back(1);
      cellsToBeSubdivided.push_back(2);
      cellsToBeSubdivided.push_back(3);
      cellsToBeSubdivided.push_back(5);
      cellsToBeSubdivided.push_back(6);
      cellsToBeSubdivided.push_back(9);

      subdivision->SetCellsToBeSubdivided(cellsToBeSubdivided);
      }
    else
      {
      subdivision->AddSubdividedCellId(0);
      subdivision->AddSubdividedCellId(1);
      subdivision->AddSubdividedCellId(2);
      subdivision->AddSubdividedCellId(3);
      subdivision->AddSubdividedCellId(5);
      subdivision->AddSubdividedCellId(6);
      subdivision->AddSubdividedCellId(9);
      }
    }

  subdivision->SetInput( reader->GetOutput() );
  subdivision->Update();
  typename OutputMeshType::Pointer output = subdivision->GetOutput();

  bool smoothing = true;
  if ( argc >= 7 )
  {
  smoothing = false;
  }

  if ( smoothing )
    {
    typedef itk::SmoothingQuadEdgeMeshFilter< OutputMeshType, OutputMeshType > OutputMeshSmoothingFilterType;
    typedef itk::OnesMatrixCoefficients< OutputMeshType >                      OnesMatrixCoefficientsType;

    OnesMatrixCoefficientsType coef;
    typename OutputMeshSmoothingFilterType::Pointer meshSmoothingFilter = OutputMeshSmoothingFilterType::New();
    meshSmoothingFilter->SetInput( output );
    meshSmoothingFilter->SetCoefficientsMethod(&coef);
    meshSmoothingFilter->SetDelaunayConforming(1);
    meshSmoothingFilter->SetNumberOfIterations(1);
    meshSmoothingFilter->Update();

    output->Graft( meshSmoothingFilter->GetOutput() );
    }

  typename WriterType::Pointer writer = WriterType::New();
  writer->SetFileName(argv[2]);
  writer->SetInput( output );

  try
    {
    writer->Update();
    }
  catch ( itk::ExceptionObject & exp )
    {
    std::cerr << "Exception thrown while writting the output file " << std::endl;
    std::cerr << exp << std::endl;
    return EXIT_FAILURE;
    }

  return EXIT_SUCCESS;
}

int itkTriangleCellSubdivisionQuadEdgeMeshFilterTest(int argc, char *argv[])
{
  if ( argc < 3 )
    {
    std::cerr << "Missing Parameters " << std::endl;
    std::cerr << "Usage: " << argv[0];
    std::cerr << " inputMeshFile  outputMeshFile subdivisionType Resolution non-uniform" << std::endl;
    std::cerr << " 0 : ModifiedButterfly " << std::endl;
    std::cerr << " 1 : Linear " << std::endl;
    std::cerr << " 2 : Loop " << std::endl;
    std::cerr << " 3 : Squarethree " << std::endl;
    return EXIT_FAILURE;
    }

  typedef float MeshPixelType;
  const unsigned int Dimension = 3;

  typedef itk::QuadEdgeMesh< MeshPixelType, Dimension > InputMeshType;
  typedef itk::QuadEdgeMesh< MeshPixelType, Dimension > OutputMeshType;

  typedef itk::ModifiedButterflyTriangleCellSubdivisionQuadEdgeMeshFilter< OutputMeshType, OutputMeshType >   ModifiedButterflySubdivisionFilterType;
  typedef itk::LinearTriangleCellSubdivisionQuadEdgeMeshFilter< OutputMeshType, OutputMeshType >      LinearSubdivisionFilterType;
  typedef itk::LoopTriangleCellSubdivisionQuadEdgeMeshFilter< OutputMeshType, OutputMeshType >        LoopSubdivisionFilterType;
  typedef itk::SquareThreeTriangleCellSubdivisionQuadEdgeMeshFilter< OutputMeshType, OutputMeshType > SquareThreeSubdivisionFilterType;

  if ( argc >= 4 )
    {
    int type = std::atoi(argv[3]);

    switch ( type )
      {
      case 0:
        return TriangleCellSubdivisionQuadEdgeMeshFilterTest< ModifiedButterflySubdivisionFilterType >( argc, argv );
      case 1:
        return TriangleCellSubdivisionQuadEdgeMeshFilterTest< LinearSubdivisionFilterType >( argc, argv );
      case 2:
        return TriangleCellSubdivisionQuadEdgeMeshFilterTest< LoopSubdivisionFilterType >( argc, argv );
      case 3:
        return TriangleCellSubdivisionQuadEdgeMeshFilterTest< SquareThreeSubdivisionFilterType >( argc, argv );
      default:
        std::cerr << "Invalid subdivision type : " << type << std::endl;
        return EXIT_FAILURE;
      }
    }
  else
    {
    std::cerr << "You must have subdivision type " << std::endl;
    return EXIT_FAILURE;
    }

  return EXIT_SUCCESS;
}
<commit_msg>Fix warnings on ITK dashboard<commit_after>/*=========================================================================
 *
 *  Copyright Insight Software Consortium
 *
 *  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.txt
 *
 *  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.
 *
 *=========================================================================*/

#include "itkModifiedButterflyTriangleCellSubdivisionQuadEdgeMeshFilter.h"
#include "itkLinearTriangleCellSubdivisionQuadEdgeMeshFilter.h"
#include "itkLoopTriangleCellSubdivisionQuadEdgeMeshFilter.h"
#include "itkSquareThreeTriangleCellSubdivisionQuadEdgeMeshFilter.h"
#include "itkIterativeTriangleCellSubdivisionQuadEdgeMeshFilter.h"
#include "itkQuadEdgeMesh.h"
#include "itkQuadEdgeMeshParamMatrixCoefficients.h"
#include "itkSmoothingQuadEdgeMeshFilter.h"
#include "itkMeshFileReader.h"
#include "itkMeshFileWriter.h"

template< typename TTriangleCellSubdivisionFilter >
int TriangleCellSubdivisionQuadEdgeMeshFilterTest( int argc, char *argv[] )
{
  typedef TTriangleCellSubdivisionFilter                         TriangleCellSubdivisionFilterType;

  typedef typename TriangleCellSubdivisionFilterType::InputMeshType    InputMeshType;
  typedef typename TriangleCellSubdivisionFilterType::OutputMeshType   OutputMeshType;

  typedef itk::IterativeTriangleCellSubdivisionQuadEdgeMeshFilter< InputMeshType, TriangleCellSubdivisionFilterType > IterativeTriangleCellSubdivisionFilterType;
  typedef typename IterativeTriangleCellSubdivisionFilterType::Pointer                                                IterativeTriangleCellSubdivisionFilterPointer;

  typedef itk::MeshFileReader< InputMeshType >  ReaderType;
  typedef itk::MeshFileWriter< OutputMeshType > WriterType;

  typename ReaderType::Pointer reader = ReaderType::New();
  reader->SetFileName( argv[1] );
  try
    {
    reader->Update();
    }
  catch ( itk::ExceptionObject & exp )
    {
    std::cerr << "Exception thrown while reading the input file " << std::endl;
    std::cerr << exp << std::endl;
    return EXIT_FAILURE;
    }

  IterativeTriangleCellSubdivisionFilterPointer subdivision = IterativeTriangleCellSubdivisionFilterType::New();

  if ( argc >= 5 )
    {
    unsigned int n = std::atoi(argv[4]);
    subdivision->SetResolutionLevels(n);
    }

  if ( argc >= 6 )
    {
    int type = std::atoi(argv[5]);
    if ( type )
      {
      typename IterativeTriangleCellSubdivisionFilterType::SubdivisionCellContainer cellsToBeSubdivided;

      cellsToBeSubdivided.push_back(0);
      cellsToBeSubdivided.push_back(1);
      cellsToBeSubdivided.push_back(2);
      cellsToBeSubdivided.push_back(3);
      cellsToBeSubdivided.push_back(5);
      cellsToBeSubdivided.push_back(6);
      cellsToBeSubdivided.push_back(9);

      subdivision->SetCellsToBeSubdivided(cellsToBeSubdivided);
      }
    else
      {
      subdivision->AddSubdividedCellId(0);
      subdivision->AddSubdividedCellId(1);
      subdivision->AddSubdividedCellId(2);
      subdivision->AddSubdividedCellId(3);
      subdivision->AddSubdividedCellId(5);
      subdivision->AddSubdividedCellId(6);
      subdivision->AddSubdividedCellId(9);
      }
    }

  subdivision->SetInput( reader->GetOutput() );
  subdivision->Update();
  typename OutputMeshType::Pointer output = subdivision->GetOutput();

  bool smoothing = true;
  if ( argc >= 7 )
  {
  smoothing = false;
  }

  if ( smoothing )
    {
    typedef itk::SmoothingQuadEdgeMeshFilter< OutputMeshType, OutputMeshType > OutputMeshSmoothingFilterType;
    typedef itk::OnesMatrixCoefficients< OutputMeshType >                      OnesMatrixCoefficientsType;

    OnesMatrixCoefficientsType coef;
    typename OutputMeshSmoothingFilterType::Pointer meshSmoothingFilter = OutputMeshSmoothingFilterType::New();
    meshSmoothingFilter->SetInput( output );
    meshSmoothingFilter->SetCoefficientsMethod(&coef);
    meshSmoothingFilter->SetDelaunayConforming(1);
    meshSmoothingFilter->SetNumberOfIterations(1);
    meshSmoothingFilter->Update();

    output->Graft( meshSmoothingFilter->GetOutput() );
    }

  typename WriterType::Pointer writer = WriterType::New();
  writer->SetFileName(argv[2]);
  writer->SetInput( output );

  try
    {
    writer->Update();
    }
  catch ( itk::ExceptionObject & exp )
    {
    std::cerr << "Exception thrown while writting the output file " << std::endl;
    std::cerr << exp << std::endl;
    return EXIT_FAILURE;
    }

  return EXIT_SUCCESS;
}

int itkTriangleCellSubdivisionQuadEdgeMeshFilterTest(int argc, char *argv[])
{
  if ( argc < 3 )
    {
    std::cerr << "Missing Parameters " << std::endl;
    std::cerr << "Usage: " << argv[0];
    std::cerr << " inputMeshFile  outputMeshFile subdivisionType Resolution non-uniform" << std::endl;
    std::cerr << " 0 : ModifiedButterfly " << std::endl;
    std::cerr << " 1 : Linear " << std::endl;
    std::cerr << " 2 : Loop " << std::endl;
    std::cerr << " 3 : Squarethree " << std::endl;
    return EXIT_FAILURE;
    }

  typedef float MeshPixelType;
  const unsigned int Dimension = 3;

  typedef itk::QuadEdgeMesh< MeshPixelType, Dimension > MeshType;

  typedef itk::ModifiedButterflyTriangleCellSubdivisionQuadEdgeMeshFilter< MeshType, MeshType > ModifiedButterflySubdivisionFilterType;
  typedef itk::LinearTriangleCellSubdivisionQuadEdgeMeshFilter< MeshType, MeshType >            LinearSubdivisionFilterType;
  typedef itk::LoopTriangleCellSubdivisionQuadEdgeMeshFilter< MeshType, MeshType >              LoopSubdivisionFilterType;
  typedef itk::SquareThreeTriangleCellSubdivisionQuadEdgeMeshFilter< MeshType, MeshType >       SquareThreeSubdivisionFilterType;

  if ( argc >= 4 )
    {
    int type = std::atoi(argv[3]);

    switch ( type )
      {
      case 0:
        return TriangleCellSubdivisionQuadEdgeMeshFilterTest< ModifiedButterflySubdivisionFilterType >( argc, argv );
      case 1:
        return TriangleCellSubdivisionQuadEdgeMeshFilterTest< LinearSubdivisionFilterType >( argc, argv );
      case 2:
        return TriangleCellSubdivisionQuadEdgeMeshFilterTest< LoopSubdivisionFilterType >( argc, argv );
      case 3:
        return TriangleCellSubdivisionQuadEdgeMeshFilterTest< SquareThreeSubdivisionFilterType >( argc, argv );
      default:
        std::cerr << "Invalid subdivision type : " << type << std::endl;
        return EXIT_FAILURE;
      }
    }
  else
    {
    std::cerr << "You must have subdivision type " << std::endl;
    return EXIT_FAILURE;
    }

  return EXIT_SUCCESS;
}
<|endoftext|>