text:
/*
 * Software License Agreement (BSD License)
 *
 *  Copyright (c) 2011, Willow Garage, Inc.
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   * Neither the name of Willow Garage, Inc. nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 *
 * @author: Koen Buys
 */

#include <pcl/gpu/people/face_detector.h>
#include <pcl/console/print.h>
#include <pcl/gpu/utils/safe_call.hpp>
#include <pcl/point_types_conversion.h>

#include <boost/foreach.hpp>
#include <boost/property_tree/xml_parser.hpp>
#include <boost/property_tree/ptree.hpp>

#include <cuda_runtime_api.h>

#define NVBIN_HAAR_SIZERESERVED     16
#define NVBIN_HAAR_VERSION          0x1

#define PCL_ASSERT_NCVSTAT(ncvOp) \
    do \
    { \
        NCVStatus _ncv_return_status = ncvOp; \
        PCL_ASSERT_ERROR_PRINT_RETURN(NCV_SUCCESS==_ncv_return_status, "ncv_return_status!=NCV_SUCCESS", _ncv_return_status); \
    } while (0)

#define PCL_ASSERT_CUDA_RETURN(cudacall, errCode) \
    do \
    { \
        cudaError_t res = cudacall; \
        ncvAssertPrintReturn(cudaSuccess==res, "cudaError_t!=cudaSuccess", errCode); \
    } while (0)

using boost::property_tree::ptree;

pcl::gpu::people::FaceDetector::FaceDetector(int cols, int rows)
{
  PCL_DEBUG("[pcl::gpu::people::FaceDetector::FaceDetector] : (D) : Constructor called\n");

  cols_ = cols; rows_ = rows;

  cuda_dev_id_ = 0;
  cudaSafeCall ( cudaSetDevice (cuda_dev_id_));
  cudaSafeCall ( cudaGetDeviceProperties (&cuda_dev_prop_, cuda_dev_id_));
  PCL_DEBUG("[pcl::gpu::people::FaceDetector::FaceDetector] : (D) : Using GPU: %d ( %s ), arch= %d . %d\n",cuda_dev_id_, cuda_dev_prop_.name, cuda_dev_prop_.major, cuda_dev_prop_.minor);

}

/**
 * \brief This loads the Haar description file from a XML file format
 */
NCVStatus
pcl::gpu::people::FaceDetector::loadFromXML2(const std::string                   &filename,
                                             HaarClassifierCascadeDescriptor     &haar,
                                             std::vector<HaarStage64>            &haar_stages,
                                             std::vector<HaarClassifierNode128>  &haarClassifierNodes,
                                             std::vector<HaarFeature64>          &haar_features)
{
  NCVStatus ncv_return_status;      // TODO remove this type

  boost::property_tree::ptree pt;

  haar.NumStages = 0;
  haar.NumClassifierRootNodes = 0;
  haar.NumClassifierTotalNodes = 0;
  haar.NumFeatures = 0;
  haar.ClassifierSize.width = 0;
  haar.ClassifierSize.height = 0;

  try   // Fetch error loading the file
  {
    read_xml(filename,pt);
  }
  catch(boost::exception const&  exb)
  {
    PCL_DEBUG("[pcl::gpu::people::FaceDetector::loadFromXML2] : (D) : Unable to read filename with boost exception\n");
    return NCV_HAAR_XML_LOADING_EXCEPTION;
  }
  catch (std::exception const&  ex)
  {
    PCL_DEBUG("[pcl::gpu::people::FaceDetector::loadFromXML2] : (D) : Unable to read filename with exception %s\n", ex.what());
    return NCV_HAAR_XML_LOADING_EXCEPTION;
  }
  catch (...)
  {
    PCL_DEBUG("[pcl::gpu::people::FaceDetector::loadFromXML2] : (D) : Unable to read filename\n");
    return NCV_HAAR_XML_LOADING_EXCEPTION;
  }

  haar.bHasStumpsOnly = true;
  haar.bNeedsTiltedII = false;

  Ncv32u cur_max_tree_depth;

  std::vector<HaarClassifierNode128> host_temp_classifier_not_root_nodes;
  haar_stages.resize(0);
  haarClassifierNodes.resize(0);
  haar_features.resize(0);

  try   // Fetch all parsing errors
  {
    int level1 = 0;     // For debug output only
    /// LEVEL1 (opencv_storage)
    BOOST_FOREACH(const ptree::value_type &top_node, pt)
    {
      if(!strcmp(top_node.first.c_str(), "opencv_storage"))      // Else NCV_HAAR_XML_LOADING_EXCEPTION
      {
        PCL_DEBUG("[pcl::gpu::people::FaceDetector::loadFromXML2] : (D) : level 1, XMLnode %d, first : %s\n", level1, top_node.first.c_str());

        int level2 = 0;
        boost::property_tree::ptree pt2 = top_node.second;

        /// LEVEL2 (haarcascade)
        BOOST_FOREACH(const ptree::value_type &w, pt2)
        {
          if(!strcmp(w.second.get("<xmlattr>.type_id","").c_str(), "opencv-haar-classifier"))                      // Else NCV_HAAR_XML_LOADING_EXCEPTION
          {
            PCL_DEBUG("[pcl::gpu::people::FaceDetector::loadFromXML2] : (D) : level 2, XMLnode %d, first : %s\n", level2, w.first.c_str());

            // Parse the size field, giving the classifier patch size
            std::string size_string  = w.second.get<std::string>("size");                                         // data field contains both width and height so we put it in string first
            std::cout << "loadFromXML2: level 2 : size string: " << size_string << std::endl;
            std::istringstream l( size_string );
            l >> std::skipws >> haar.ClassifierSize.width >> haar.ClassifierSize.height;
            if ( !l || haar.ClassifierSize.width <= 0 || haar.ClassifierSize.height <= 0 )
            {
              PCL_WARN("[pcl::gpu::people::FaceDetector::loadFromXML2] : (D) : level 2 : size node format error\n");   //  format error: line doesn't start with an int.
              return (NCV_HAAR_XML_LOADING_EXCEPTION);
            }
            else
              PCL_DEBUG("[pcl::gpu::people::FaceDetector::loadFromXML2] : (D) : level2 : size int1 %d, int2 %d\n", haar.ClassifierSize.width, haar.ClassifierSize.height);

            int level3 = 0;
            /// LEVEL3 (Stages)
            BOOST_FOREACH(const ptree::value_type &stage, w.second.get_child("stages"))
            {
              PCL_DEBUG("[pcl::gpu::people::FaceDetector::loadFromXML2] : (D) : level 3, XMLnode %d, first : %s\n", level3, stage.first.c_str());

              HaarStage64 current_stage;
              current_stage.setStartClassifierRootNodeOffset(haarClassifierNodes.size());
              Ncv32u tmp_num_classifier_root_nodes = 0;

              float stage_threshold = stage.second.get<float>("stage_threshold");
              int parent = stage.second.get<int>("parent");
              int next = stage.second.get<int>("next");

              current_stage.setStageThreshold(stage_threshold);

              PCL_DEBUG("[pcl::gpu::people::FaceDetector::loadFromXML2] : (D) : level 3 stage_threshold %f, parent %d, next %d\n", stage_threshold, parent, next);

              int level4 = 0;
              /// LEVEL4 (Trees)
              BOOST_FOREACH(const ptree::value_type &tree, stage.second.get_child("trees"))
              {
                PCL_DEBUG("[pcl::gpu::people::FaceDetector::loadFromXML2] : (D) : level 4, XMLnode %d, first : %s\n", level4, tree.first.c_str());
                Ncv32u node_identifier = 0;

                int level5 = 0;
                ptree root = tree.second;

                /// LEVEL5 (Root_node)
                BOOST_FOREACH(const ptree::value_type &root_node, root)
                {
                  PCL_DEBUG("[pcl::gpu::people::FaceDetector::loadFromXML2] : (D) : level 5, node %d, first : %s\n", level5, root_node.first.c_str());

                  if(!strcmp(root_node.first.c_str(), "_"))
                  {
                    HaarClassifierNode128 current_node;

                    float node_threshold = root_node.second.get<float>("threshold");
                    float left_val = root_node.second.get<float>("left_val");         // TODO Test if left node is available! see Nvidia code for solution
                    bool left_val_available = true;                                   // TODO set correctly
                    float right_val = root_node.second.get<float>("right_val");
                    bool right_val_available = true;                                  // TODO set correctly
                    bool tilted = root_node.second.get<bool>("feature.tilted");

                    current_node.setThreshold(node_threshold);

                    PCL_DEBUG("[pcl::gpu::people::FaceDetector::loadFromXML2] : (D) : level 5 node_threshold %f, left_val %f, right_val %f, tilted %d\n", node_threshold, left_val, right_val, tilted);

                    HaarClassifierNodeDescriptor32 node_left;
                    ncv_return_status = node_left.create(left_val);                              // TODO check ncv_return_status return value line below and return
                    current_node.setLeftNodeDesc(node_left);

                    HaarClassifierNodeDescriptor32 node_right;
                    ncv_return_status = node_right.create(right_val);
                    current_node.setRightNodeDesc(node_right);

                    haar.bNeedsTiltedII = (tilted != 0);
                    Ncv32u feature_identifier = 0;

                    /// LEVEL6 (Rects)
                    BOOST_FOREACH(const ptree::value_type &rect, root_node.second.get_child("feature.rects"))
                    {
                      PCL_DEBUG("[pcl::gpu::people::FaceDetector::loadFromXML2] : (D) : level 6, first : %s\n", rect.first.c_str());

                      std::string r = rect.second.data();

                      std::istringstream re( r );
                      int rectangle_u = 0, rectangle_v = 0, rectangle_width = 0, rectangle_height =0;
                      float rectWeight = 0;
                      re >> std::skipws >> rectangle_u >> rectangle_v >> rectangle_width >> rectangle_height >> rectWeight;

                      if ( !re )
                      {
                        //  format error: line doesn't start with an int.
                        PCL_WARN("[pcl::gpu::people::FaceDetector::loadFromXML2] : (W) : level 6 : rect format error\n");
                      }
                      else
                      {
                        PCL_DEBUG("[pcl::gpu::people::FaceDetector::loadFromXML2] : (D) : level 6 : rectangle_u %d, rectangle_v %d, rectW %d, rectH %d, rectWeight %f\n", rectangle_u, rectangle_v, rectangle_width, rectangle_height, rectWeight);
                        HaarFeature64 current_feature;
                        ncv_return_status = current_feature.setRect(rectangle_u, rectangle_v, rectangle_width, rectangle_height, haar.ClassifierSize.width, haar.ClassifierSize.height);
                        current_feature.setWeight(rectWeight);
                        PCL_ASSERT_NCVSTAT(ncv_return_status);
                        haar_features.push_back(current_feature);
                        feature_identifier++;
                      }
                    }

                    HaarFeatureDescriptor32 temp_feature_descriptor;
                    ncv_return_status = temp_feature_descriptor.create(haar.bNeedsTiltedII, left_val_available, right_val_available, feature_identifier, haar_features.size() - feature_identifier);

                    //ncv_return_status = temp_feature_descriptor.create(haar.bNeedsTiltedII, feature_identifier, haar_features.size() - feature_identifier);
                    ncvAssertReturn(NCV_SUCCESS == ncv_return_status, ncv_return_status);
                    current_node.setFeatureDesc(temp_feature_descriptor);

                    if (!node_identifier)
                    {
                        //root node
                        haarClassifierNodes.push_back(current_node);
                        cur_max_tree_depth = 1;
                    }
                    else
                    {
                        //other node
                        host_temp_classifier_not_root_nodes.push_back(current_node);
                        // TODO replace with PCL_DEBUG in the future
                        PCL_INFO("[pcl::gpu::people::FaceDetector::loadFromXML2] : (I) : Found non root node number %d", host_temp_classifier_not_root_nodes.size());
                        cur_max_tree_depth++;
                    }
                    node_identifier++;
                  }
                  else
                    PCL_WARN("[pcl::gpu::people::FaceDetector::loadFromXML2] : (W) : Found fifth level node that is atypical : %s\n", root_node.first.c_str());
                  level5++;
                }
                tmp_num_classifier_root_nodes++;
                level4++;
              }

              current_stage.setNumClassifierRootNodes(tmp_num_classifier_root_nodes);
              haar_stages.push_back(current_stage);

              // TODO make this DEBUG later on
              PCL_INFO("[pcl::gpu::people::FaceDetector::loadFromXML2] : (I) : level 3 stage %d loaded with %d Root Nodes, %f Threshold, %d Root Node Offset", haar_stages.size(), tmp_num_classifier_root_nodes, current_stage.getStartClassifierRootNodeOffset());

              level3++;
            }
          }
          else   // Probably we stumbled upon a comment at this level or somebody adjusted the XML file
            PCL_WARN("loadFromXML2: Found second level node that is atypical : %s\n", w.first.c_str());
        }
        level2++;
      }
      else
      {
        PCL_WARN("[pcl::gpu::people::FaceDetector::loadFromXML2] : (W) : Found first level node that is atypical : %s\n", top_node.first.c_str());
        return (NCV_HAAR_XML_LOADING_EXCEPTION);
      }
      level1++;
    }
  }
  catch(boost::exception const&  exb)
  {
    PCL_DEBUG("[pcl::gpu::people::FaceDetector::loadFromXML2] : (D) : Unable to process content with boost exception\n");
    return (NCV_HAAR_XML_LOADING_EXCEPTION);
  }
  catch (std::exception const&  ex)
  {
    PCL_DEBUG("[pcl::gpu::people::FaceDetector::loadFromXML2] : (D) : Unable to process content with std exception %s\n", ex.what());
    return (NCV_HAAR_XML_LOADING_EXCEPTION);
  }
  catch (...)
  {
    PCL_DEBUG("[pcl::gpu::people::FaceDetector::loadFromXML2] : (D) : Unable to process content\n");
    return (NCV_HAAR_XML_LOADING_EXCEPTION);
  }

  //fill in cascade stats
  haar.NumStages = haar_stages.size();
  haar.NumClassifierRootNodes = haarClassifierNodes.size();
  haar.NumClassifierTotalNodes = haar.NumClassifierRootNodes + host_temp_classifier_not_root_nodes.size();
  haar.NumFeatures = haar_features.size();

  //merge root and leaf nodes in one classifiers array, leaf nodes are sorted behind the root nodes
  Ncv32u offset_root = haarClassifierNodes.size();

  for (Ncv32u i=0; i<haarClassifierNodes.size(); i++)
  {
      HaarClassifierNodeDescriptor32 node_left = haarClassifierNodes[i].getLeftNodeDesc();
      if (!node_left.isLeaf())
      {
          Ncv32u new_offset = node_left.getNextNodeOffset() + offset_root;
          node_left.create(new_offset);
      }
      haarClassifierNodes[i].setLeftNodeDesc(node_left);

      HaarClassifierNodeDescriptor32 node_right = haarClassifierNodes[i].getRightNodeDesc();
      if (!node_right.isLeaf())
      {
          Ncv32u new_offset = node_right.getNextNodeOffset() + offset_root;
          node_right.create(new_offset);
      }
      haarClassifierNodes[i].setRightNodeDesc(node_right);
  }

  for (Ncv32u i=0; i<host_temp_classifier_not_root_nodes.size(); i++)
  {
      HaarClassifierNodeDescriptor32 node_left = host_temp_classifier_not_root_nodes[i].getLeftNodeDesc();
      if (!node_left.isLeaf())
      {
          Ncv32u new_offset = node_left.getNextNodeOffset() + offset_root;
          node_left.create(new_offset);
      }
      host_temp_classifier_not_root_nodes[i].setLeftNodeDesc(node_left);

      HaarClassifierNodeDescriptor32 node_right = host_temp_classifier_not_root_nodes[i].getRightNodeDesc();
      if (!node_right.isLeaf())
      {
          Ncv32u new_offset = node_right.getNextNodeOffset() + offset_root;
          node_right.create(new_offset);
      }
      host_temp_classifier_not_root_nodes[i].setRightNodeDesc(node_right);

      haarClassifierNodes.push_back(host_temp_classifier_not_root_nodes[i]);
  }
  return (NCV_SUCCESS);
}

/**
 * \brief This loads the Haar description file from a NVBIN file format
 */
NCVStatus
pcl::gpu::people::FaceDetector::loadFromNVBIN(const std::string &filename,
                               HaarClassifierCascadeDescriptor &haar,
                               std::vector<HaarStage64> &haar_stages,
                               std::vector<HaarClassifierNode128> &haarClassifierNodes,
                               std::vector<HaarFeature64> &haar_features)
{
    size_t readCount;
    FILE *fp = fopen(filename.c_str(), "rb");
    ncvAssertReturn(fp != NULL, NCV_FILE_ERROR);
    Ncv32u fileVersion;
    readCount = fread(&fileVersion, sizeof(Ncv32u), 1, fp);
    PCL_ASSERT_ERROR_PRINT_RETURN(1 == readCount, "return NCV_FILE_ERROR", NCV_FILE_ERROR);
    PCL_ASSERT_ERROR_PRINT_RETURN(fileVersion == NVBIN_HAAR_VERSION, "return NCV_FILE_ERROR", NCV_FILE_ERROR);
    Ncv32u fsize;
    readCount = fread(&fsize, sizeof(Ncv32u), 1, fp);
    PCL_ASSERT_ERROR_PRINT_RETURN(1 == readCount, "return NCV_FILE_ERROR", NCV_FILE_ERROR);
    fseek(fp, 0, SEEK_END);
    Ncv32u fsizeActual = ftell(fp);
    PCL_ASSERT_ERROR_PRINT_RETURN(fsize == fsizeActual, "return NCV_FILE_ERROR", NCV_FILE_ERROR);

    std::vector<unsigned char> fdata;
    fdata.resize(fsize);
    Ncv32u dataOffset = 0;
    fseek(fp, 0, SEEK_SET);
    readCount = fread(&fdata[0], fsize, 1, fp);
    PCL_ASSERT_ERROR_PRINT_RETURN(1 == readCount, "return NCV_FILE_ERROR", NCV_FILE_ERROR);
    fclose(fp);

    //data
    dataOffset = NVBIN_HAAR_SIZERESERVED;
    haar.NumStages = *(Ncv32u *)(&fdata[0]+dataOffset);
    dataOffset += sizeof(Ncv32u);
    haar.NumClassifierRootNodes = *(Ncv32u *)(&fdata[0]+dataOffset);
    dataOffset += sizeof(Ncv32u);
    haar.NumClassifierTotalNodes = *(Ncv32u *)(&fdata[0]+dataOffset);
    dataOffset += sizeof(Ncv32u);
    haar.NumFeatures = *(Ncv32u *)(&fdata[0]+dataOffset);
    dataOffset += sizeof(Ncv32u);
    haar.ClassifierSize = *(NcvSize32u *)(&fdata[0]+dataOffset);
    dataOffset += sizeof(NcvSize32u);
    haar.bNeedsTiltedII = *(NcvBool *)(&fdata[0]+dataOffset);
    dataOffset += sizeof(NcvBool);
    haar.bHasStumpsOnly = *(NcvBool *)(&fdata[0]+dataOffset);
    dataOffset += sizeof(NcvBool);

    haar_stages.resize(haar.NumStages);
    haarClassifierNodes.resize(haar.NumClassifierTotalNodes);
    haar_features.resize(haar.NumFeatures);

    Ncv32u szStages = haar.NumStages * sizeof(HaarStage64);
    Ncv32u szClassifiers = haar.NumClassifierTotalNodes * sizeof(HaarClassifierNode128);
    Ncv32u szFeatures = haar.NumFeatures * sizeof(HaarFeature64);

    memcpy(&haar_stages[0], &fdata[0]+dataOffset, szStages);
    dataOffset += szStages;
    memcpy(&haarClassifierNodes[0], &fdata[0]+dataOffset, szClassifiers);
    dataOffset += szClassifiers;
    memcpy(&haar_features[0], &fdata[0]+dataOffset, szFeatures);
    dataOffset += szFeatures;

    return NCV_SUCCESS;
}

/*
 * \brief Depending on file format load the Haar description file
 */
NCVStatus
pcl::gpu::people::FaceDetector::ncvHaarLoadFromFile_host(const std::string &filename,
                                   HaarClassifierCascadeDescriptor &haar,
                                   NCVVector<HaarStage64> &h_haar_stages,
                                   NCVVector<HaarClassifierNode128> &h_haar_nodes,
                                   NCVVector<HaarFeature64> &h_haar_features)
{
    PCL_ASSERT_ERROR_PRINT_RETURN(h_haar_stages.memType() == NCVMemoryTypeHostPinned &&
                                  h_haar_nodes.memType() == NCVMemoryTypeHostPinned &&
                                  h_haar_features.memType() == NCVMemoryTypeHostPinned, "return NCV_MEM_RESIDENCE_ERROR", NCV_MEM_RESIDENCE_ERROR);

    NCVStatus ncv_return_status;

    std::string fext = filename.substr(filename.find_last_of(".") + 1);
    std::transform(fext.begin(), fext.end(), fext.begin(), ::tolower);

    std::vector<HaarStage64> haar_stages;
    std::vector<HaarClassifierNode128> haar_nodes;
    std::vector<HaarFeature64> haar_features;

    if (fext == "nvbin")
    {
        ncv_return_status = loadFromNVBIN(filename, haar, haar_stages, haar_nodes, haar_features);
        PCL_ASSERT_NCVSTAT(ncv_return_status);
    }
    else if (fext == "xml")
    {
        ncv_return_status = loadFromXML2(filename, haar, haar_stages, haar_nodes, haar_features);
        PCL_ASSERT_NCVSTAT(ncv_return_status);
    }
    else
    {
        return NCV_HAAR_XML_LOADING_EXCEPTION;
    }

    PCL_ASSERT_ERROR_PRINT_RETURN(h_haar_stages.length() >= haar_stages.size(), "Return NCV_MEM_INSUFFICIENT_CAPACITY", NCV_MEM_INSUFFICIENT_CAPACITY);
    PCL_ASSERT_ERROR_PRINT_RETURN(h_haar_nodes.length() >= haar_nodes.size(), "Return NCV_MEM_INSUFFICIENT_CAPACITY", NCV_MEM_INSUFFICIENT_CAPACITY);
    PCL_ASSERT_ERROR_PRINT_RETURN(h_haar_features.length() >= haar_features.size(), "Return NCV_MEM_INSUFFICIENT_CAPACITY", NCV_MEM_INSUFFICIENT_CAPACITY);

    memcpy(h_haar_stages.ptr(), &haar_stages[0], haar_stages.size()*sizeof(HaarStage64));
    memcpy(h_haar_nodes.ptr(), &haar_nodes[0], haar_nodes.size()*sizeof(HaarClassifierNode128));
    memcpy(h_haar_features.ptr(), &haar_features[0], haar_features.size()*sizeof(HaarFeature64));

    return NCV_SUCCESS;
}

/*
 * \brief Scans the Haar description file for the sizes of the Stages, Nodes and Features
 */
NCVStatus
pcl::gpu::people::FaceDetector::ncvHaarGetClassifierSize(const std::string &filename,
                                                         Ncv32u &numStages,
                                                         Ncv32u &numNodes,
                                                         Ncv32u &numFeatures)
{
    size_t readCount;
    NCVStatus ncv_return_status;

    std::string fext = filename.substr(filename.find_last_of(".") + 1);
    std::transform(fext.begin(), fext.end(), fext.begin(), ::tolower);

    if (fext == "nvbin")
    {
        FILE *fp = fopen(filename.c_str(), "rb");
        PCL_ASSERT_ERROR_PRINT_RETURN(fp != NULL, "Return NCV_FILE_ERROR", NCV_FILE_ERROR);
        Ncv32u fileVersion;
        readCount = fread(&fileVersion, sizeof(Ncv32u), 1, fp);
        PCL_ASSERT_ERROR_PRINT_RETURN(1 == readCount, "Return NCV_FILE_ERROR", NCV_FILE_ERROR);
        PCL_ASSERT_ERROR_PRINT_RETURN(fileVersion == NVBIN_HAAR_VERSION, "Return NCV_FILE_ERROR", NCV_FILE_ERROR);
        fseek(fp, NVBIN_HAAR_SIZERESERVED, SEEK_SET);
        Ncv32u tmp;
        readCount = fread(&numStages,   sizeof(Ncv32u), 1, fp);
        PCL_ASSERT_ERROR_PRINT_RETURN(1 == readCount, "Return NCV_FILE_ERROR", NCV_FILE_ERROR);
        readCount = fread(&tmp,         sizeof(Ncv32u), 1, fp);
        PCL_ASSERT_ERROR_PRINT_RETURN(1 == readCount, "Return NCV_FILE_ERROR", NCV_FILE_ERROR);
        readCount = fread(&numNodes,    sizeof(Ncv32u), 1, fp);
        PCL_ASSERT_ERROR_PRINT_RETURN(1 == readCount, "Return NCV_FILE_ERROR", NCV_FILE_ERROR);
        readCount = fread(&numFeatures, sizeof(Ncv32u), 1, fp);
        PCL_ASSERT_ERROR_PRINT_RETURN(1 == readCount, "Return NCV_FILE_ERROR", NCV_FILE_ERROR);
        fclose(fp);
    }
    else if (fext == "xml")
    {
        HaarClassifierCascadeDescriptor haar;
        std::vector<HaarStage64> haar_stages;
        std::vector<HaarClassifierNode128> haar_nodes;
        std::vector<HaarFeature64> haar_features;

        ncv_return_status = loadFromXML2(filename, haar, haar_stages, haar_nodes, haar_features);
        PCL_ASSERT_NCVSTAT(ncv_return_status);    // TODO convert this to PCL methodS

        numStages = haar.NumStages;
        numNodes = haar.NumClassifierTotalNodes;
        numFeatures = haar.NumFeatures;
    }
    else
    {
        return NCV_HAAR_XML_LOADING_EXCEPTION;
    }

    return NCV_SUCCESS;
}

/*
 * \brief the Wrapper that calls the actual Nvidia code
 */
NCVStatus
pcl::gpu::people::FaceDetector::NCVprocess(pcl::PointCloud<pcl::RGB>&           cloud_in,
                                           pcl::PointCloud<pcl::Intensity32u>&  cloud_out,
                                           HaarClassifierCascadeDescriptor      &haar,
                                           NCVVector<HaarStage64>               &d_haar_stages,
                                           NCVVector<HaarClassifierNode128>     &d_haar_nodes,
                                           NCVVector<HaarFeature64>             &d_haar_features,
                                           NCVVector<HaarStage64>               &h_haar_stages,
                                           INCVMemAllocator                     &gpu_allocator,
                                           INCVMemAllocator                     &cpu_allocator,
                                           cudaDeviceProp                       &device_properties,
                                           Ncv32u                               width,
                                           Ncv32u                               height,
                                           NcvBool                              bFilterRects,
                                           NcvBool                              bLargestFace)
{
  pcl::PointCloud<Intensity32u>  input_gray;

  PointCloudRGBtoI(cloud_in, input_gray);

  cloud_out.width = input_gray.width;
  cloud_out.height = input_gray.height;
  cloud_out.points.resize (input_gray.points.size ());

  PCL_ASSERT_ERROR_PRINT_RETURN(!gpu_allocator.isCounting(),"retcode=NCV_NULL_PTR", NCV_NULL_PTR);

  NCVStatus ncv_return_status;

  NCV_SET_SKIP_COND(gpu_allocator.isCounting());

  NCVMatrixAlloc<Ncv8u> d_src(gpu_allocator, width, height);
  PCL_ASSERT_ERROR_PRINT_RETURN(d_src.isMemAllocated(), "retcode=NCV_ALLOCATOR_BAD_ALLOC", NCV_ALLOCATOR_BAD_ALLOC);
  NCVMatrixAlloc<Ncv8u> h_src(cpu_allocator, width, height);
  PCL_ASSERT_ERROR_PRINT_RETURN(h_src.isMemAllocated(), "retcode=NCV_ALLOCATOR_BAD_ALLOC", NCV_ALLOCATOR_BAD_ALLOC);
  NCVVectorAlloc<NcvRect32u> d_rects(gpu_allocator, 100);
  PCL_ASSERT_ERROR_PRINT_RETURN(d_rects.isMemAllocated(), "retcode=NCV_ALLOCATOR_BAD_ALLOC", NCV_ALLOCATOR_BAD_ALLOC);

  NCV_SKIP_COND_BEGIN

  for(int i=0; i<input_gray.points.size(); i++)
  {
    memcpy(h_src.ptr(), &input_gray.points[i].intensity, sizeof(input_gray.points[i].intensity));
  }

  ncv_return_status = h_src.copySolid(d_src, 0);
  PCL_ASSERT_NCVSTAT(ncv_return_status);
  PCL_ASSERT_CUDA_RETURN(cudaStreamSynchronize(0), NCV_CUDA_ERROR);

  NCV_SKIP_COND_END

  NcvSize32u roi;
  roi.width = d_src.width();
  roi.height = d_src.height();

  Ncv32u number_of_detections;
  ncv_return_status = ncvDetectObjectsMultiScale_device ( d_src,
                                                roi,
                                                d_rects,
                                                number_of_detections,
                                                haar,
                                                h_haar_stages,
                                                d_haar_stages,
                                                d_haar_nodes,
                                                d_haar_features,
                                                haar.ClassifierSize,
                                                (bFilterRects || bLargestFace) ? 4 : 0,
                                                1.2f,
                                                1,
                                                (bLargestFace ? NCVPipeObjDet_FindLargestObject : 0) | NCVPipeObjDet_VisualizeInPlace,
                                                gpu_allocator,
                                                cpu_allocator,
                                                device_properties,
                                                0);

  PCL_ASSERT_NCVSTAT(ncv_return_status);
  PCL_ASSERT_CUDA_RETURN(cudaStreamSynchronize(0), NCV_CUDA_ERROR);

  NCV_SKIP_COND_BEGIN

  ncv_return_status = d_src.copySolid(h_src, 0);
  PCL_ASSERT_NCVSTAT(ncv_return_status);
  PCL_ASSERT_CUDA_RETURN(cudaStreamSynchronize(0), NCV_CUDA_ERROR);

  // Copy result back into output cloud
  for(int i=0; i<cloud_out.points.size(); i++)
  {
    memcpy(&cloud_out.points[i].intensity, h_src.ptr() /* + i * ??? */, sizeof(cloud_out.points[i].intensity));
  }

  NCV_SKIP_COND_END

  return NCV_SUCCESS;
}

/*
 * \brief This does the GPU allocations and configurations
 */
int
pcl::gpu::people::FaceDetector::configure(std::string cascade_file_name)
{
  cascade_file_name_ = cascade_file_name;

  // Load the classifier from file (assuming its size is about 1 mb), using a simple allocator
  gpu_allocator_ = new NCVMemNativeAllocator(NCVMemoryTypeDevice, static_cast<Ncv32u>(cuda_dev_prop_.textureAlignment));
  PCL_ASSERT_ERROR_PRINT_RETURN(gpu_allocator_->isInitialized(), "[pcl::gpu::people::FaceDetector::FaceDetector] : Error creating cascade GPU allocator", -1);

  cpu_allocator_ = new NCVMemNativeAllocator(NCVMemoryTypeHostPinned, static_cast<Ncv32u>(cuda_dev_prop_.textureAlignment));
  PCL_ASSERT_ERROR_PRINT_RETURN(cpu_allocator_->isInitialized(), "[pcl::gpu::people::FaceDetector::FaceDetector] : Error creating cascade CPU allocator", -1);

  NCVStatus ncv_return_status;
  Ncv32u haarNumStages, haarNumNodes, haarNumFeatures;

  ncv_return_status = ncvHaarGetClassifierSize(cascade_file_name_, haarNumStages, haarNumNodes, haarNumFeatures);
  PCL_ASSERT_ERROR_PRINT_RETURN(ncv_return_status == NCV_SUCCESS, "[pcl::gpu::people::FaceDetector::FaceDetector] : Error reading classifier size (check the file)", -1);

  haar_stages_host_ = new NCVVectorAlloc<HaarStage64>(*cpu_allocator_, haarNumStages);
  PCL_ASSERT_ERROR_PRINT_RETURN(haar_stages_host_->isMemAllocated(), "[pcl::gpu::people::FaceDetector::FaceDetector] : Error in cascade CPU allocator", -1);

  haar_nodes_host_ = new NCVVectorAlloc<HaarClassifierNode128>(*cpu_allocator_, haarNumNodes);
  PCL_ASSERT_ERROR_PRINT_RETURN(haar_nodes_host_->isMemAllocated(), "[pcl::gpu::people::FaceDetector::FaceDetector] : Error in cascade CPU allocator", -1);

  haar_features_host_ = new NCVVectorAlloc<HaarFeature64>(*cpu_allocator_, haarNumFeatures);
  PCL_ASSERT_ERROR_PRINT_RETURN(haar_features_host_->isMemAllocated(), "[pcl::gpu::people::FaceDetector::FaceDetector] : Error in cascade CPU allocator", -1);

  ncv_return_status = ncvHaarLoadFromFile_host(cascade_file_name_, haar_clas_casc_descr_, *haar_stages_host_, *haar_nodes_host_, *haar_features_host_);
  PCL_ASSERT_ERROR_PRINT_RETURN(ncv_return_status == NCV_SUCCESS, "[pcl::gpu::people::FaceDetector::FaceDetector] : Error loading classifier", -1);

  haar_stages_dev_ = new NCVVectorAlloc<HaarStage64>(*gpu_allocator_, haarNumStages);
  PCL_ASSERT_ERROR_PRINT_RETURN(haar_stages_dev_->isMemAllocated(), "[pcl::gpu::people::FaceDetector::FaceDetector] : Error in cascade GPU allocator", -1);

  haar_nodes_dev_ = new NCVVectorAlloc<HaarClassifierNode128>(*gpu_allocator_, haarNumNodes);
  PCL_ASSERT_ERROR_PRINT_RETURN(haar_nodes_dev_->isMemAllocated(), "[pcl::gpu::people::FaceDetector::FaceDetector] : Error in cascade GPU allocator", -1);

  haar_features_dev_ = new NCVVectorAlloc<HaarFeature64>(*gpu_allocator_, haarNumFeatures);
  PCL_ASSERT_ERROR_PRINT_RETURN(haar_features_dev_->isMemAllocated(), "[pcl::gpu::people::FaceDetector::FaceDetector] : Error in cascade GPU allocator", -1);

  ncv_return_status = haar_stages_host_->copySolid(*haar_stages_dev_, 0);
  PCL_ASSERT_ERROR_PRINT_RETURN(ncv_return_status == NCV_SUCCESS, "[pcl::gpu::people::FaceDetector::FaceDetector] : Error copying cascade to GPU", -1);
  ncv_return_status = haar_nodes_host_->copySolid(*haar_nodes_dev_, 0);
  PCL_ASSERT_ERROR_PRINT_RETURN(ncv_return_status == NCV_SUCCESS, "[pcl::gpu::people::FaceDetector::FaceDetector] : Error copying cascade to GPU", -1);
  ncv_return_status = haar_features_host_->copySolid(*haar_features_dev_, 0);
  PCL_ASSERT_ERROR_PRINT_RETURN(ncv_return_status == NCV_SUCCESS, "[pcl::gpu::people::FaceDetector::FaceDetector] : Error copying cascade to GPU", -1);

  // Calculate memory requirements and create real allocators
  gpu_counter_ = new NCVMemStackAllocator(static_cast<Ncv32u>(cuda_dev_prop_.textureAlignment));
  PCL_ASSERT_ERROR_PRINT_RETURN(gpu_counter_->isInitialized(), "[pcl::gpu::people::FaceDetector::FaceDetector] : Error creating GPU memory counter", -1);

  cpu_counter_ = new NCVMemStackAllocator(static_cast<Ncv32u>(cuda_dev_prop_.textureAlignment));
  PCL_ASSERT_ERROR_PRINT_RETURN(cpu_counter_->isInitialized(), "[pcl::gpu::people::FaceDetector::FaceDetector] : Error creating CPU memory counter", -1);

  // TODO fix this fake call
  /*
  ncv_return_status = NCVprocess (NULL, cols_, rows_,
                        false, false, haar,
                        d_haar_stages, d_haar_nodes,
                        d_haar_features, h_haar_stages,
                        gpuCounter, cpuCounter, cuda_dev_prop_);
  PCL_ASSERT_ERROR_PRINT_RETURN(ncv_return_status == NCV_SUCCESS, "[pcl::gpu::people::FaceDetector::FaceDetector] : Error in memory counting pass", -1);
  */

  gpu_stack_allocator_ = new NCVMemStackAllocator(NCVMemoryTypeDevice, gpu_counter_->maxSize(), static_cast<Ncv32u>(cuda_dev_prop_.textureAlignment));
  PCL_ASSERT_ERROR_PRINT_RETURN(gpu_stack_allocator_->isInitialized(), "[pcl::gpu::people::FaceDetector::FaceDetector] : Error creating GPU memory allocator", -1);

  cpu_stack_allocator_ = new NCVMemStackAllocator(NCVMemoryTypeHostPinned, cpu_counter_->maxSize(), static_cast<Ncv32u>(cuda_dev_prop_.textureAlignment));
  PCL_ASSERT_ERROR_PRINT_RETURN(cpu_stack_allocator_->isInitialized(), "[pcl::gpu::people::FaceDetector::FaceDetector] : Error creating CPU memory allocator", -1);

  PCL_DEBUG("[pcl::gpu::people::FaceDetector::FaceDetector] : (D) : Initialized for frame size [%dx%d]\n", cols_, rows_);

  return 1;
}

void
pcl::gpu::people::FaceDetector::setDeviceId( int id )
{
  cuda_dev_id_ = id;
  cudaSafeCall ( cudaSetDevice (cuda_dev_id_));
  cudaSafeCall ( cudaGetDeviceProperties (&cuda_dev_prop_, cuda_dev_id_));
}

void
pcl::gpu::people::FaceDetector::process(pcl::PointCloud<pcl::RGB>& cloud_in,
                                        pcl::PointCloud<pcl::Intensity32u>& cloud_out)
{
  PCL_DEBUG("[pcl::gpu::people::FaceDetector::process] : (D) : called\n");
  cols_ = cloud_in.width; rows_ = cloud_in.height;

  // TODO do something with the NCVStatus return value
  NCVStatus status = NCVprocess(cloud_in,
                                cloud_out,
                                haar_clas_casc_descr_,
                                *haar_stages_dev_,
                                *haar_nodes_dev_,
                                *haar_features_dev_,
                                *haar_stages_host_,
                                *gpu_allocator_,
                                *cpu_allocator_,
                                cuda_dev_prop_,
                                cloud_in.width,
                                cloud_in.height,
                                filter_rects_,
                                largest_object_);

}

max_stars_repo_name: avinfinity/UnmanagedCodeSnippets


text:
/*
** EPITECH PROJECT, 2018
** Epitech scolarship project (4 years remaining)
** File description:
**      Made on 2018/11 by ebernard
*/

#ifndef R_TYPE_TCPMANAGER_HPP
#define R_TYPE_TCPMANAGER_HPP

#include <boost/asio.hpp>
#include "TcpSocket.hpp"
#include "ISocketManager.hpp"

namespace network
{
	class TcpManager : public ISocketManager
	{
	public:
		TcpManager(int port);
		~TcpManager();

		size_t Connect(std::string &ip, int port);

		int Write(int id, std::string &) override;
		int Write(std::string &ip, int port, std::string &toSend) override;

		bool requestIsEmpty() const override;
		requestInfo getLastRequest() override;

		std::string getIp() override;
		int getPort() override;
		void startAccept();
		const std::queue<requestInfo> &getRequests() const override;

		void removeClosedSocket() override;
	private:
		void handleAccept(std::shared_ptr<TcpSocket> new_connection, const boost::system::error_code &error);

		std::string firstGetIp();

		boost::asio::io_service m_io;
		std::shared_ptr<std::thread> m_ioRunThread;
		boost::asio::ip::tcp::endpoint m_endPoint;
		boost::asio::ip::tcp::acceptor m_acceptor;

		std::vector<std::shared_ptr<TcpSocket>> m_client;
		std::queue<requestInfo> m_request;
		int m_listenPort;
		std::string m_localIp;
	};
}

#else

namespace network {
	class TcpManager;
};

#endif // R_TYPE_TCPMANAGER_HPP

ext: hpp

max_stars_repo_name: KillianG/R-Type

max_issues_repo_name: KillianG/R-Type

max_forks_repo_name: KillianG/R-Type


text:
/**
 * Copyright (c) 2015 Johannes Reifferscheid
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
 * associated documentation files (the "Software"), to deal in the Software without restriction,
 * including without limitation the rights to use, copy, modify, merge, publish, distribute,
 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies or
 * substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
 * NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */
#define BOOST_TEST_MODULE vlad_tests
#include <boost/test/unit_test.hpp>

#include <algorithm>
#include <array>
#include <ctime>
#include <functional>
#include <iostream>
#include <iterator>
#include <map>
#include <random>
#include <string>
#include <vector>

#define DEBUG
#include <levenshtein.hpp>
#include <trie.hpp>
#include <utf8.hpp>

using namespace vlad;
using namespace vlad::trie;
using namespace vlad::levenshtein;

static uint32_t levenshtein_distance(const std::string& s1, const std::string& s2) {
	const size_t len1 = s1.size();
	const size_t len2 = s2.size();
	std::vector<uint32_t> col(len2 + 1);
	std::vector<uint32_t> prevCol(len2 + 1);

	for (unsigned int i = 0; i < prevCol.size(); i++)
		prevCol[i] = i;

	for (unsigned int i = 0; i < len1; i++) {
		col[0] = i + 1;
		for (unsigned int j = 0; j < len2; j++)
			col[j + 1] = std::min(std::min(1 + col[j], 1 + prevCol[1 + j]),
			                      prevCol[j] + (s1[i] == s2[j] ? 0 : 1));
		col.swap(prevCol);
	}

	return prevCol[len2];
}

// adapted from
// https://en.wikipedia.org/wiki/Damerau–Levenshtein_distance#Optimal_string_alignment_distance
static uint32_t optimal_string_alignment(const std::string& s1, const std::string& s2) {
	std::vector<std::vector<size_t>> d(s1.size() + 1, std::vector<size_t>(s2.size() + 1));

	std::array<std::vector<size_t>, 3> cols;
	cols.fill(std::vector<size_t>(s2.size() + 1));

	for (size_t i = 0; i <= s2.size(); ++i) {
		cols[0][i] = i;
	}

	for (size_t i = 0; i < s1.size(); i++) {
		auto& prev_col = cols[(i + 2) % 3];
		auto& crnt_col = cols[i % 3];
		auto& next_col = cols[(i + 1) % 3];
		next_col[0] = i + 1;

		for (size_t j = 0; j < s2.size(); j++) {
			auto cost = (s1[i] == s2[j]) ? 0 : 1;

			next_col[j + 1] =
			    std::min(std::min(crnt_col[j + 1] + 1, next_col[j] + 1), crnt_col[j] + cost);
			if (i > 0 && j > 0 && (s1[i] == s2[j - 1] && s1[i - 1] == s2[j])) {
				next_col[j + 1] = std::min(next_col[j + 1], prev_col[j - 1] + cost);
			}
		}
	}
	return cols[s1.size() % 3][s2.size()];
}

static void enumerate_strings(int max_length, std::function<void(const std::string&)> callback,
                              const std::string& prefix = "") {
	callback(prefix);
	if (max_length > 0) {
		enumerate_strings(max_length - 1, callback, prefix + "0");
		enumerate_strings(max_length - 1, callback, prefix + "1");
		enumerate_strings(max_length - 1, callback, prefix + "2");
	}
}

#ifdef DEBUG
#if 0
static void print_state(const levenshtein_automaton& a, const levenshtein_matcher<>& m) {
	const auto& positions = a.nfa.states[m.state.id].positions;
	for (const auto& pos : positions) {
		std::cout << "(" << (pos.i + m.state.pos) << ", " << pos.e << (pos.trans ? "t" : "") << ")";
	}
	std::cout << std::endl;
}
#endif
#endif

static std::vector<uint32_t> to_utf32(const std::string& s) {
	std::vector<uint32_t> result;
	::utf8::to_utf32(s.begin(), s.end(), std::back_inserter(result));
	return result;
}

BOOST_AUTO_TEST_SUITE(trie_tests)

template <typename V>
void simple_trie_test(V visitor) {
	word_index index;

	auto insert = [&](const std::string& s, uint32_t val) {
		auto v = to_utf32(s);
		index.insert(v.begin(), v.end(), val);
	};

	visitor(insert);

#ifdef DEBUG
	index.print();
#endif

	levenshtein_automaton a0(0, false);

	visitor([&](const std::string& s, uint32_t val) {
		size_t call_count = 0;
		uint32_t value = 0;
		levenshtein_matcher<> m0(a0, s);
		index.find(m0, [&](vector_wrapper val) {
			++call_count;
			BOOST_REQUIRE(val->size() == 1);
			value = (*val)[0];
		});

		BOOST_CHECK_MESSAGE(call_count == 1, s << ": call_count = " << call_count);
		BOOST_CHECK_MESSAGE(value == val, s << ": value = " << value);
	});
}

bool verify_fuzz(const word_index& index, const levenshtein_automaton& a,
                 const std::vector<uint32_t>& key, const std::vector<uint32_t>& docs) {
	levenshtein_matcher<profiles::utf32::naive> m(a, key);

	bool result = true;
	size_t call_count = 0;
	index.find(m, [&](vector_wrapper val) {
		++call_count;
		result &= *val == docs;
	});

	if (!result || call_count != 1) {
		std::cout << "fuzz test failed for key {";
		for (auto v : key)
			std::cout << v << ", ";
		std::cout << "} with call_count = " << call_count;
		std::cout << std::endl;
	}

	return result && call_count == 1;
}

template <typename V>
void u16_trie_test(V visitor) {
	word_index index;

	auto inserter = [&](const std::vector<uint32_t>& v, uint32_t val) {
		index.insert(v.begin(), v.end(), val);
	};

	levenshtein_automaton a(0, false);
	auto verifier = [&](const std::vector<uint32_t>& v, uint32_t val) {
		BOOST_CHECK(verify_fuzz(index, a, v, { val }));
	};

	visitor(inserter);
	visitor(verifier);
}

BOOST_AUTO_TEST_CASE(utf8) {
	/*
	confirms that this file is encoded correctly
	*/
	std::string s = "ﬀ";
	auto iter = s.begin();
	uint32_t codepoint = ::utf8::next_codepoint(iter, s.end());

	BOOST_CHECK(codepoint == 0xFB00);
}

BOOST_AUTO_TEST_CASE(empty) {
	/*
	confirms that the empty string is handled correctly.
	*/
	simple_trie_test([](auto cb) { cb("", 1); });
}

BOOST_AUTO_TEST_CASE(prefix) {
	/*
	confirms that inserting a new value whose key is a prefix of a previously inserted
	value works.
	*/

	simple_trie_test([](auto cb) {
		cb("hello world", 1);
		cb("hello", 2);
	});
}

BOOST_AUTO_TEST_CASE(compound) {
	/*
	confirms that inserting values with code points >= 32768 works
	*/

	simple_trie_test([](auto cb) {
		cb("aﬁbﬂc", 1);
		cb("aﬂbﬂc", 2);
		cb("aﬂﬂﬂc", 3);
	});
}

BOOST_AUTO_TEST_CASE(long_tail) {
	/*
	confirms that splitting a leaf works when the new key is very long
	*/
	simple_trie_test([](auto cb) {
		cb("13", 1);
		cb("123456789012345", 2);
	});
}

BOOST_AUTO_TEST_CASE(full_tail_prefix) {
	/*
	confirms that splitting a leaf works when the splitted leaf has a full tail and is a prefix of
	the new key
	*/
	simple_trie_test([](auto cb) {
		cb("12345678901", 1);
		cb("123456789012345", 2);
	});
}

BOOST_AUTO_TEST_CASE(full_tail_same) {
	/*
	confirms that inserting a value works when there's already an entry for the key and the entry's
	leaf has a full tail.
	*/
	std::string str("012345678901234567890");
	auto codepoints = to_utf32(str);

	for (size_t len = 2; len < str.size(); ++len) {
		word_counter index;

		index.insert(codepoints.begin(), codepoints.begin() + len, { 1, 0 });
		index.insert(codepoints.begin(), codepoints.begin() + len, { 2, 1 });
		BOOST_CHECK_EQUAL(1, index.size());

#ifdef DEBUG
		index.print();
#endif

		levenshtein_automaton a0(0, false);

		size_t call_count = 0;
		word_counter::value_type value;
		levenshtein_matcher<> m0(a0, std::string(str.begin(), str.begin() + len));
		index.find(m0, [&](const word_counter::value_type& val) {
			++call_count;
			value = val;
		});

		BOOST_CHECK_EQUAL(1, call_count);
		BOOST_CHECK_EQUAL(3, value.count);
		BOOST_CHECK_EQUAL(1, value.max_document_id);
	}
}

BOOST_AUTO_TEST_CASE(wide) {
	/*
	confirms that inner nodes with more than 4 children work.
	*/

	std::vector<std::string> strs{ "aaa", "aba", "aca", "ada", "aea", "afa", "aga" };
	simple_trie_test([&](auto cb) {
		uint32_t n = 0;
		for (const auto& str : strs)
			cb(str, ++n);
	});
}

bool fuzz_test(size_t seed, const std::vector<bool> mask, int maxlen = -1, bool print = false) {
	/*
	Generates random test data. If the test data triggers a bug, finds a minimal subset of the data
	that still triggers the bug and outputs code for a test case.
	*/

	std::map<std::vector<uint32_t>, std::vector<uint32_t>> entries;

	std::uniform_int_distribution<> len(0, 15);
	std::uniform_int_distribution<> chars(1, 100000);

	word_index index;

	std::mt19937 rd;
	rd.seed(seed);
	std::vector<uint32_t> v;

	if (print) {
		std::cout << "BOOST_AUTO_TEST_CASE(fuzz_test_" << seed << ") {" << std::endl;
		std::cout << "\tauto visitor = [](auto cb) {" << std::endl;
	}

	size_t size = 0;
	for (uint32_t i = 0; i < mask.size(); ++i) {
		v.clear();

		int l = len(rd);
		for (int j = 0; j < l; ++j) {
			int chr = chars(rd);
			if (maxlen > 0 && j >= maxlen - 1)
				continue;

			v.push_back(chr);
		}

		if (mask[i]) {
			++size;

			if (print) {
				std::cout << "\t\tcb({";
				std::copy(v.begin(), v.end(), std::ostream_iterator<int>(std::cout, ", "));
				std::cout << "}, " << i << ");" << std::endl;
			}

			std::vector<uint32_t>& docs = entries[v];
			docs.push_back(i);

			index.insert(v.begin(), v.end(), i);
		}
	}

	if (print) {
		std::cout << "\t};" << std::endl;
		std::cout << "\tu16_trie_test(visitor);" << std::endl;
		std::cout << "}" << std::endl;
	}

	// verify entries
	rd.seed(seed);
	bool result = true;

	levenshtein_automaton a0(0, false);
	for (const auto& e : entries) {
		bool this_elem = verify_fuzz(index, a0, e.first, e.second);
		result &= this_elem;
	}

	return result;
}

BOOST_AUTO_TEST_CASE(fuzz) {
	size_t seed = time(nullptr);

	std::cout << "seed: " << seed << std::endl;
	std::vector<bool> mask(1024, true);

	if (!fuzz_test(seed, mask)) {
		for (size_t step_size = mask.size() / 2; step_size > 0; step_size >>= 1) {
			std::cout << "step size: " << step_size << std::endl;
			for (size_t pos = 0; pos < mask.size(); pos += step_size) {
				if (!mask[pos])
					continue;
				for (size_t i = 0; i < step_size; ++i)
					mask[pos + i] = false;

				// if the test doesn't still fail, re-enable this chunk
				if (fuzz_test(seed, mask)) {
					for (size_t i = 0; i < step_size; ++i)
						mask[pos + i] = true;
				}
			}
		}

		int max_len = 20;
		while (max_len > 0 && !fuzz_test(seed, mask, max_len, false))
			--max_len;

		BOOST_CHECK(fuzz_test(seed, mask, max_len + 1, true));
	} else {
		BOOST_CHECK(true);
	}
}

BOOST_AUTO_TEST_CASE(basic) {
	word_index index;

	// insert strings
	uint32_t n = 0;
	enumerate_strings(5, [&](const std::string& s1) {
		BOOST_TEST_CHECKPOINT("inserting " << s1);
		auto u32 = to_utf32(s1);
		index.insert(u32.begin(), u32.end(), ++n);
	});

	uint32_t dist = n;
	enumerate_strings(5, [&](const std::string& s1) {
		BOOST_TEST_CHECKPOINT("inserting " << s1);
		auto u32 = to_utf32(s1);
		index.insert(u32.begin(), u32.end(), ++n);
	});

	levenshtein_automaton a0(0, false);
	// check that strings are in the index
	n = 0;
	enumerate_strings(5, [&](const std::string& s1) {
		size_t call_count = 0;
		uint32_t value = 0;

		levenshtein_matcher<> m0(a0, s1);
		index.find(m0, [&](vector_wrapper val) {
			++call_count;
			BOOST_REQUIRE(val->size() == 2);
			value = (*val)[0];
			BOOST_CHECK((*val)[1] - (*val)[0] == dist);
		});

		++n;
		BOOST_CHECK_MESSAGE(call_count == 1, s1 << ": call_count was " << call_count);
		BOOST_CHECK_MESSAGE(value == n, s1 << ": value = " << value << " != " << n);
	});
}

BOOST_AUTO_TEST_SUITE_END()

BOOST_AUTO_TEST_SUITE(str_mask)

BOOST_AUTO_TEST_CASE(differential_str_mask) {
	/*
	 * Confirms that the different str mask implementations do the same thing.
	 */

	enumerate_strings(6, [](const std::string& s) {
		profiles::ansi::precomputed<> ansi_pre(s, 2);
		profiles::utf32::naive utf32_naive(to_utf32(s), 2);

#ifdef __SSE4_2__
		profiles::ansi::sse ansi_sse(s, 2);
#endif

		for (int i = 0; i < 6; ++i) {
			for (char c = '0'; c <= '3'; ++c) {
				BOOST_CHECK_EQUAL(ansi_pre(i, c), utf32_naive(i, c));
#ifdef __SSE4_2__
				BOOST_CHECK_EQUAL(ansi_pre(i, c), ansi_sse(i, c));
#endif
			}
		}
	});
}

BOOST_AUTO_TEST_SUITE_END()

BOOST_AUTO_TEST_SUITE(levenshtein)

BOOST_AUTO_TEST_CASE(no_trans) {
	/*
	 * Confirms that levenshtein-automata with max_distance = 0, 1, 2 and no transpositions
	 * accept the right words.
	 */

	levenshtein_automaton a0(0, false);
	levenshtein_automaton a1(1, false);
	levenshtein_automaton a2(2, false);

	enumerate_strings(5, [&](const std::string& s1) {
		enumerate_strings(5, [&](const std::string& s2) {
			int dist = levenshtein_distance(s1, s2);

			levenshtein_matcher<> m0(a0, s1);
			levenshtein_matcher<> m1(a1, s1);
			levenshtein_matcher<> m2(a2, s1);

			for (char c : s2) {
				m0.next(c);
				m1.next(c);
				m2.next(c);
			}

			BOOST_CHECK_MESSAGE((dist == 0) == m0.accepted(), s1 << " vs. " << s2
			                                                     << " not accepted by m0");
			BOOST_CHECK_MESSAGE((dist <= 1) == m1.accepted(), s1 << " vs. " << s2
			                                                     << " not accepted by m1");
			BOOST_CHECK_MESSAGE((dist <= 2) == m2.accepted(), s1 << " vs. " << s2
			                                                     << " not accepted by m2");
		});
	});
}

BOOST_AUTO_TEST_CASE(trans) {
	/*
	 * Confirms that levenshtein-automata with max_distance = 0, 1, 2 and transpositions
	 * accept the right words.
	 */

	levenshtein_automaton a0(0, true);
	levenshtein_automaton a1(1, true);
	levenshtein_automaton a2(2, true);

	enumerate_strings(5, [&](const std::string& s1) {
		enumerate_strings(5, [&](const std::string& s2) {
			int dist = optimal_string_alignment(s1, s2);

			levenshtein_matcher<> m0(a0, s1);
			levenshtein_matcher<> m1(a1, s1);
			levenshtein_matcher<> m2(a2, s1);

			for (char c : s2) {
				m0.next(c);
				m1.next(c);
				m2.next(c);
			}

			BOOST_CHECK_MESSAGE((dist == 0) == m0.accepted(), s1 << " vs. " << s2
			                                                     << (m0.accepted() ? "" : " not")
			                                                     << " accepted by m0");
			BOOST_CHECK_MESSAGE((dist <= 1) == m1.accepted(), s1 << " vs. " << s2
			                                                     << (m1.accepted() ? "" : " not")
			                                                     << " accepted by m1");
			BOOST_CHECK_MESSAGE((dist <= 2) == m2.accepted(), s1 << " vs. " << s2
			                                                     << (m2.accepted() ? "" : " not")
			                                                     << " accepted by m2");
		});
	});
}

BOOST_AUTO_TEST_SUITE_END()

ext: cpp

max_stars_repo_name: jreiffers/vlad

max_issues_repo_name: jreiffers/vlad

max_forks_repo_name: jreiffers/vlad


text:
/* Main.cpp (exercise 2.8)
Description:
	* Solutions to exercise 2.8 problems 1-5.

*/

#include <bitset>
#include <boost\dynamic_bitset\dynamic_bitset.hpp>
#include <functional>
#include <iostream>
#include <limits>
#include <stdexcept>
#include <vector>
#include "BitMatrix.hpp"
#include "Functions.hpp"

int main()
{
	/* 2.8.1 */
	// a) Create bitsets from unsigned long and unsigned long long:
	unsigned long long ull = std::numeric_limits<unsigned long long>::max(); // 8 bytes
	unsigned long ul = std::numeric_limits<unsigned long>::max();		  // 4 bytes

	std::bitset<sizeof(ull)> set1(ull);
	std::bitset<sizeof(ul)> set2(ul);
	std::cout << "ULL maximum in binary: " << set1 << std::endl;
	std::cout << "UL maximum in binary: " << set2 << std::endl;
	// b) Create bitsets from full strings:
	std::bitset<sizeof(ull)> set3("01100010101");
	std::bitset<sizeof(ul)> set4("111111101");
	std::bitset<12> set5("0110101010101", 5, 0, 5);
	std::bitset<12> set6(435);
	// Print results:
	std::cout << "Bitsets generated from strings: " << std::endl;
	std::cout << set3 << std::endl;
	std::cout << set4 << std::endl;
	std::cout << set5 << std::endl;
	// c) Use exception handling to check for out-of-range values and invalid arguments:
	std::cout << "Testing bitset exceptions: " << std::endl;
	// Test out of range exception:
	try
	{
		std::bitset<5> set7("1111111111111111");
		// Note: below causes fatal run-time error, therefore cannot customize exception handling for out_of_range:
		//set6[12];
	}
	catch (std::out_of_range &err)
	{
		std::cout << "Out of range exception caught: " << std::endl;
		std::cout << err.what() << std::endl;
	}
	// Test invalid argument exception:
	try
	{
		std::bitset<12> set8("222111");
	}
	catch (std::invalid_argument &err)
	{
		std::cout << "Invalid bitset argument caught: " << std::endl;
		std::cout << err.what() << std::endl;
	}
	// d) Set bits in bitset in different ways:
	// Test reset():
	std::cout << "For " << set5 << std::endl;
	std::cout << "reset(): " << set5.reset() << std::endl;
	// Test flip():
	std::cout << "flip(): " << set5.flip() << std::endl;
	// Test none():
	std::cout << "none(): " << set5.none() << std::endl;
	// Test any():
	std::cout << "any(): " << set5.any() << std::endl;
	// Test operator[]:
	std::cout << "bit at index 3: " << set5[3] << std::endl;
	// Count number of set bits:
	std::cout << "number of bits in set: " << set5.size() << std::endl;
	// e) Convert bitset to a string, unsigned long and unsigned long long:
	std::cout << "as a string: " << set5.to_string() << std::endl;
	std::cout << "as unsigned long: " << set5.to_ulong() << std::endl;
	std::cout << "as unsigned long long: " << set5.to_ullong() << std::endl;
	// f) Test bitset equality:
	std::cout << set5 << " == " << set6 << ": " << (set5 == set6) << std::endl;
	// Note that bitsets must be same size for boolean comparison operators to work.

	/* 2.8.2 */
	// a) Create two same sized bitsets:
	std::bitset<10> bs1, bs2;
	// b) Toggle all bits of bs1 and bs2:
	bs1.flip(); bs2.flip();
	// c) Test bitwise XOR, OR, AND:
	std::cout << "Testing XOR, OR and AND: " << std::endl;
	std::cout << bs1 << std::endl;
	std::cout << bs2 << std::endl;

	std::cout << "XOR: " << (bs1 ^ bs2) << std::endl;;
	std::cout << "OR: " << (bs1 | bs2) << std::endl;;
	std::cout << "AND: " << (bs1 & bs2) << std::endl;
	// d) Perform right and left shift operations:
	bs1 << 1;
	bs2 >> 2;
	std::cout << "Single left shifting on bs1: " << bs1 << std::endl;
	std::cout << "Two right shifting on bs2: " << bs2 << std::endl;
	////// TODO: fix:

	// e) Use std::hash to created hashed values for bs1 and bs2:
	std::hash<std::bitset<10>> hash_func;
	std::cout << "Hash of " << bs1 << ": " << hash_func(bs1) << std::endl;
	std::cout << "Hash of " << bs2 << ": " << hash_func(bs2) << std::endl;

	/* 2.8.3 */
	// a) Port questions 1 and 2 to use boost::dynamic_bitset<T>:
	// Note that cannot convert an unsigned long long into a bitset (maximum size is unsigned long):
	// boost::dynamic_bitset<> boost_set1 { sizeof(ull), ull };
	boost::dynamic_bitset<> boost_set2{ sizeof(ul), ul };

	std::cout << "Testing boost::dynamic_bitset<bool>: " << std::endl;
	// std::cout << "ULL maximum in binary: " << boost_set1 << std::endl;
	std::cout << "UL maximum in binary: " << boost_set2 << std::endl;
	// b) Create boost::dynamic_bitsets from full strings:
	boost::dynamic_bitset<> boost_set3{ std::string("01100010101") };
	boost::dynamic_bitset<> boost_set4{ std::string("111111101") };
	// Create dynamic bitset by passing string and specifying starting index:
	boost::dynamic_bitset<> boost_set5{ std::string("0110101010101"), 1 };
	// Create dynamic bitset from passed integral literal:
	boost::dynamic_bitset<> boost_set6{ 435 };
	// Print results:
	std::cout << "Boost Bitsets generated from strings: " << std::endl;
	std::cout << boost_set3 << std::endl;
	std::cout << boost_set4 << std::endl;
	std::cout << boost_set5 << std::endl;
	// c) Use exception handling to check for out-of-range values and invalid arguments:
	std::cout << "Testing boost::dynamic_bitset exceptions: " << std::endl;
	// Test out of range exception:
	try
	{
		boost::dynamic_bitset<> boost_set7{ 12, 300 };
		// Note: below causes fatal run-time error, therefore cannot customize exception handling for out_of_range:
		//boost_set7[2000];
	}
	catch (std::out_of_range &err)
	{
		std::cout << "Out of range exception caught: " << std::endl;
		std::cout << err.what() << std::endl;
	}
	// Test invalid argument exception:
	try
	{
		std::bitset<12> set8("222111");
	}
	catch (std::invalid_argument &err)
	{
		std::cout << "Invalid bitset argument caught: " << std::endl;
		std::cout << err.what() << std::endl;
	}
	// d) Set bits in bitset in different ways:
	// Test reset():
	std::cout << "For " << boost_set5 << std::endl;
	std::cout << "reset(): " << boost_set5.reset() << std::endl;
	// Test flip():
	std::cout << "flip(): " << boost_set5.flip() << std::endl;
	// Test none():
	std::cout << "none(): " << boost_set5.none() << std::endl;
	// Test any():
	std::cout << "any(): " << boost_set5.any() << std::endl;
	// Test operator[]:
	std::cout << "bit at index 3: " << boost_set5[3] << std::endl;
	// Count number of set bits:
	std::cout << "number of bits in set: " << boost_set5.size() << std::endl;
	// e) Convert bitset to a string, unsigned long and unsigned long long:
	// Note that to_string() and to_ullong() not supported by dynamic bitset.
	std::cout << "as unsigned long: " << boost_set5.to_ulong() << std::endl;
	// f) Test boost::dynamic_bitset equality:
	std::cout << boost_set5 << " == " << boost_set6 << ": " << (boost_set5 == boost_set6) << std::endl;
	// Note that bitsets must be same size for boolean comparison operators to work.

	/* 2.8.2 (Boost Version) */
	// Note: dynamic_bitset<> prints all bits, while bitset prints only up until the most significant bit.
	// a) Create two same sized bitsets:
	boost::dynamic_bitset<>  boost_bs1, boost_bs2;
	// b) Toggle all bits of bs1 and bs2:
	boost_bs1.flip(); boost_bs2.flip();
	// c) Test bitwise XOR, OR, AND:
	std::cout << "Testing XOR, OR and AND: " << std::endl;
	std::cout << boost_bs2 << std::endl;
	std::cout << boost_bs2 << std::endl;

	std::cout << "XOR: " << (boost_bs1 ^ boost_bs2) << std::endl;;
	std::cout << "OR: " << (boost_bs1 | boost_bs2) << std::endl;;
	std::cout << "AND: " << (boost_bs1 & boost_bs2) << std::endl;
	// d) Perform right and left shift operations:
	boost_bs1 << 1;
	boost_bs2 >> 2;
	std::cout << "Single left shifting on bs1: " << bs1 << std::endl;
	std::cout << "Two right shifting on bs2: " << bs2 << std::endl;

	// e) Use std::hash to created hashed values for boost_bs1 and boost_bs2:
	/*std::hash<boost::dynamic_bitset<>> boost_hash_func;
	std::cout << "Hash of " << boost_bs1 << ": " << boost_hash_func(bs1) << std::endl;
	std::cout << "Hash of " << boost_bs2 << ": " << boost_hash_func(bs2) << std::endl;

	/* 2.8.3 continued: */
	// b) Test dynamic functionality of boost::dynamic_bitset:
	boost::dynamic_bitset<> dynamic{ 12, 2323 };

	// Test resize():
	std::cout << "For " << dynamic << std::endl;
	dynamic.resize(13, true); // Prepends a 1 to front if true, 0 if false.
	std::cout << "resize(13, true): " << dynamic << std::endl;
	// Test clear():
	dynamic.clear();
	std::cout << "clear(): " << dynamic << std::endl;
	// Test push_back():
	dynamic.push_back(true);
	std::cout << "push_back(true): " << dynamic << std::endl;
	// Test pop_back():
	dynamic.pop_back();
	std::cout << "pop_back(): " << dynamic << std::endl;
	// Test append():
	dynamic.append(1); // Appends an unsigned long's worth of bits (32).
	std::cout << "append(1): " << dynamic << std::endl;
	// c) Test if bitset is subset/proper subset of another bitset (note that is_subset_of() requires that passed dynamic_bitset<> have same number of bits loaded, or else run-time exception thrown):
	boost::dynamic_bitset<> dynamic2{ 32, 1 };
	std::cout << dynamic2 << " is a subset of " << dynamic << ": " << dynamic2.is_subset_of(dynamic) << std::endl;
	std::cout << dynamic2 << " is a proper subset of " << dynamic << ": " << dynamic2.is_proper_subset_of(dynamic) << std::endl;
	// d) Test find_first() and find_next():
	boost::dynamic_bitset<> dynamic3{ 12, 2002 };
	std::cout << "For " << dynamic3 << std::endl;
	std::cout << "find_first(): " << dynamic3.find_first() << std::endl;
	std::cout << "find_next(): " << dynamic3.find_next(1) << std::endl;

	/* 2.8.4 */
	// a) Compare vector<bool> bit related functionality to bitset's and dynamic_bitset<>'s:
	std::vector<bool> vectorBitset(8, false), vectorBitset2(8, false);
	std::bitset<8> bitset1(343), bitset2(654);
	// Forced to use function to convert unsigned long longs to vector bitsets, since no constructor available:
	ConvertULLToVectorBitset(vectorBitset, 343);
	ConvertULLToVectorBitset(vectorBitset2, 654);

	std::cout << "Comparing vector bitsets vs bitsets: " << std::endl;
	std::cout << "For " << VectorBitsetToString(vectorBitset) << " and " << VectorBitsetToString(vectorBitset2) << std::endl;
	// Test AND:
	std::cout << "AND bitsets: " << (bitset1 & bitset2) << std::endl;
	std::cout << "AND vectors: " << VectorBitsetToString(AND(vectorBitset, vectorBitset2)) << std::endl;
	// Test OR:
	bitset1 = 343;
	bitset2 = 654;
	std::cout << "OR bitsets: " << (bitset1 | bitset2) << std::endl;
	std::cout << "OR vectors: " << VectorBitsetToString(OR(vectorBitset, vectorBitset2)) << std::endl;
	// Test XOR:
	bitset1 = 343;
	bitset2 = 654;
	std::cout << "XOR bitsets: " << (bitset1 ^ bitset2) << std::endl;
	std::cout << "XOR vectors: " << VectorBitsetToString(XOR(vectorBitset, vectorBitset2)) << std::endl;
	// b) Test the Intersection function:
	std::cout << "Intersection of vector bitsets " << VectorBitsetToString(vectorBitset) << " and " << VectorBitsetToString(vectorBitset2) << std::endl;
	std::cout << VectorBitsetToString(Intersection(vectorBitset, vectorBitset2)) << std::endl;

	/* 2.8.5 */
	// Test full functionality of BitMatrix:
	BitMatrix<8, 8> bm1(345);
	BitMatrix<2, 2> bm2(220);
	BitMatrix<2, 2> bm3(121);

	std::cout << "For 8 x 8 BitMatrix: " << bm1 << std::endl;
	std::cout << "trueCount(): " << bm1.trueCount() << std::endl;
	std::cout << "flip(): " << bm1.flip() << std::endl;
	std::cout << "reset(): " << bm1.reset() << std::endl;
	std::cout << "all(): " << bm1.all() << std::endl;
	std::cout << "none(): " << bm1.none() << std::endl;
	std::cout << "any(): " << bm1.any() << std::endl;
	std::cout << "At(0, 0): " << bm1.At(0, 0) << std::endl;
	try
	{
		std::cout << "At(9, 9): " << bm1.At(9, 9) << std::endl;
	}
	catch (std::out_of_range &err)
	{
		std::cout << "Out of range exception caught: " << err.what() << std::endl;
	}
	// Test boolean operators:
	std::cout << "For BitMatrices: " << bm2 << "\n and " << bm3 << ":" << std::endl;
	std::cout << "AND: " << (bm2 & bm3) << std::endl;
	std::cout << "OR: " << (bm2 | bm3) << std::endl;
	std::cout << "XOR: " << (bm2 ^ bm3) << std::endl;

	system("pause");

	return 0;
}

max_stars_repo_path: Advanced C++ Course/Benjamin Rutan HW 2 Submission/2.8/Main.cpp

max_stars_repo_name: BRutan/Cpp

max_issues_repo_name: BRutan/Cpp

max_forks_repo_name: BRutan/Cpp


text:
// Copyright (C) 2014-2017 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#ifndef VSOMEIP_V3_CLIENT_ENDPOINT_IMPL_HPP_
#define VSOMEIP_V3_CLIENT_ENDPOINT_IMPL_HPP_

#include <condition_variable>
#include <deque>
#include <mutex>
#include <vector>
#include <atomic>
#include <chrono>

#include <boost/array.hpp>
#include <boost/asio/io_service.hpp>
#include <boost/asio/strand.hpp>
#include <boost/asio/ip/udp.hpp>
#include <boost/utility.hpp>
#include <vsomeip/constants.hpp>

#include "buffer.hpp"
#include "endpoint_impl.hpp"
#include "client_endpoint.hpp"
#include "tp.hpp"

namespace vsomeip_v3 {

class endpoint;
class endpoint_host;

template<typename Protocol>
class client_endpoint_impl: public endpoint_impl<Protocol>, public client_endpoint,
        public std::enable_shared_from_this<client_endpoint_impl<Protocol> > {
public:
    typedef typename Protocol::endpoint endpoint_type;
    typedef typename Protocol::socket socket_type;

    client_endpoint_impl(const std::shared_ptr<endpoint_host>& _endpoint_host,
                         const std::shared_ptr<routing_host>& _routing_host,
                         const endpoint_type& _local, const endpoint_type& _remote,
                         boost::asio::io_service &_io,
                         std::uint32_t _max_message_size,
                         configuration::endpoint_queue_limit_t _queue_limit,
                         const std::shared_ptr<configuration>& _configuration);
    virtual ~client_endpoint_impl();

    bool send(const uint8_t *_data, uint32_t _size);
    bool send(const std::vector<byte_t>& _cmd_header, const byte_t *_data,
              uint32_t _size);
    bool send_to(const std::shared_ptr<endpoint_definition> _target,
                 const byte_t *_data, uint32_t _size);
    bool send_error(const std::shared_ptr<endpoint_definition> _target,
                const byte_t *_data, uint32_t _size);
    bool flush();

    void prepare_stop(endpoint::prepare_stop_handler_t _handler, service_t _service);
    virtual void stop();
    virtual void restart(bool _force = false) = 0;

    bool is_client() const;

    bool is_established() const;
    bool is_established_or_connected() const;
    void set_established(bool _established);
    void set_connected(bool _connected);
    virtual bool get_remote_address(boost::asio::ip::address &_address) const;
    virtual std::uint16_t get_remote_port() const;

    std::uint16_t get_local_port() const;
    virtual bool is_reliable() const = 0;

    size_t get_queue_size() const;

public:
    void connect_cbk(boost::system::error_code const &_error);
    void wait_connect_cbk(boost::system::error_code const &_error);
    virtual void send_cbk(boost::system::error_code const &_error,
                          std::size_t _bytes, const message_buffer_ptr_t& _sent_msg);
    void flush_cbk(boost::system::error_code const &_error);

public:
    virtual void connect() = 0;
    virtual void receive() = 0;
    virtual void print_status() = 0;

protected:
    enum class cei_state_e : std::uint8_t {
        CLOSED,
        CONNECTING,
        CONNECTED,
        ESTABLISHED
    };
    virtual void send_queued() = 0;
    virtual void get_configured_times_from_endpoint(
            service_t _service, method_t _method,
            std::chrono::nanoseconds *_debouncing,
            std::chrono::nanoseconds *_maximum_retention) const = 0;
    void shutdown_and_close_socket(bool _recreate_socket);
    void shutdown_and_close_socket_unlocked(bool _recreate_socket);
    void start_connect_timer();
    typename endpoint_impl<Protocol>::cms_ret_e check_message_size(
            const std::uint8_t * const _data, std::uint32_t _size);
    bool check_queue_limit(const uint8_t *_data, std::uint32_t _size) const;
    void queue_train(bool _queue_size_zero_on_entry);

protected:
    mutable std::mutex socket_mutex_;
    std::unique_ptr<socket_type> socket_;
    const endpoint_type remote_;

    boost::asio::steady_timer flush_timer_;

    std::mutex connect_timer_mutex_;
    boost::asio::steady_timer connect_timer_;
    std::atomic<uint32_t> connect_timeout_;
    std::atomic<cei_state_e> state_;
    std::atomic<std::uint32_t> reconnect_counter_;

    // send data
    train train_;

    std::deque<message_buffer_ptr_t> queue_;
    std::size_t queue_size_;

    mutable std::mutex mutex_;

    std::atomic<bool> was_not_connected_;

    std::atomic<std::uint16_t> local_port_;

    boost::asio::io_service::strand strand_;

private:
    virtual void set_local_port() = 0;
    virtual std::string get_remote_information() const = 0;
    virtual bool tp_segmentation_enabled(service_t _service,
                                         method_t _method) const = 0;
    virtual std::uint32_t get_max_allowed_reconnects() const = 0;
    virtual void max_allowed_reconnects_reached() = 0;
    void send_segments(const tp::tp_split_messages_t &_segments);
    void wait_until_debounce_time_reached() const;
};

} // namespace vsomeip_v3

#endif // VSOMEIP_V3_CLIENT_ENDPOINT_IMPL_HPP_

max_stars_repo_name: lixiaolia/ndk-someip-lib

max_issues_repo_name: lixiaolia/ndk-someip-lib

max_forks_repo_name: lixiaolia/ndk-someip-lib


text:
#include "uscxml/config.h"
#include "uscxml/Interpreter.h"
#include "uscxml/interpreter/InterpreterMonitor.h"
#include "uscxml/interpreter/Logging.h"
#include <iostream>
#include <boost/algorithm/string.hpp>
#include <xercesc/util/PlatformUtils.hpp>

#ifdef _WIN32
#include "XGetopt.h"
#endif

int startedAt;
int lastTransitionAt;

using namespace uscxml;
using namespace XERCESC_NS;

enum CallbackType {
	USCXML_BEFOREPROCESSINGEVENT,
	USCXML_BEFOREMICROSTEP,
	USCXML_BEFOREEXITINGSTATE,
	USCXML_AFTEREXITINGSTATE,
	USCXML_BEFOREEXECUTINGCONTENT,
	USCXML_AFTEREXECUTINGCONTENT,
	USCXML_BEFOREUNINVOKING,
	USCXML_AFTERUNINVOKING,
	USCXML_BEFORETAKINGTRANSITION,
	USCXML_AFTERTAKINGTRANSITION,
	USCXML_BEFOREENTERINGSTATE,
	USCXML_AFTERENTERINGSTATE,
	USCXML_BEFOREINVOKING,
	USCXML_AFTERINVOKING,
	USCXML_AFTERMICROSTEP,
	USCXML_ONSTABLECONFIGURATION,
	USCXML_BEFORECOMPLETION,
	USCXML_AFTERCOMPLETION
};

std::list<CallbackType> callBackSeq;

#define CHECK_CALLBACK_TYPE(type)\
{\
	assert(!callBackSeq.empty());\
	assert(callBackSeq.front() == type);\
	callBackSeq.pop_front();\
}

class SequenceCheckingMonitor : public InterpreterMonitor {
	virtual void beforeProcessingEvent(const std::string& sessionId, const Event& event) {
		CHECK_CALLBACK_TYPE(USCXML_BEFOREPROCESSINGEVENT);
	}
	virtual void beforeMicroStep(const std::string& sessionId) {
		CHECK_CALLBACK_TYPE(USCXML_BEFOREMICROSTEP);
	}

	virtual void beforeExitingState(const std::string& sessionId, const std::string& stateName, const XERCESC_NS::DOMElement* state) {
		CHECK_CALLBACK_TYPE(USCXML_BEFOREEXITINGSTATE);
	}
	virtual void afterExitingState(const std::string& sessionId, const std::string& stateName, const XERCESC_NS::DOMElement* state) {
		CHECK_CALLBACK_TYPE(USCXML_AFTEREXITINGSTATE);
	}

	virtual void beforeExecutingContent(const std::string& sessionId, const XERCESC_NS::DOMElement* element) {
		CHECK_CALLBACK_TYPE(USCXML_BEFOREEXECUTINGCONTENT);
	}
	virtual void afterExecutingContent(const std::string& sessionId, const XERCESC_NS::DOMElement* element) {
		CHECK_CALLBACK_TYPE(USCXML_AFTEREXECUTINGCONTENT);
	}

	virtual void beforeUninvoking(const std::string& sessionId, const XERCESC_NS::DOMElement* invokeElem, const std::string& invokeid) {
		CHECK_CALLBACK_TYPE(USCXML_BEFOREUNINVOKING);
	}
	virtual void afterUninvoking(const std::string& sessionId, const XERCESC_NS::DOMElement* invokeElem, const std::string& invokeid) {
		CHECK_CALLBACK_TYPE(USCXML_AFTERUNINVOKING);
	}

	virtual void beforeTakingTransition(const std::string& sessionId, const XERCESC_NS::DOMElement* transition) {
		CHECK_CALLBACK_TYPE(USCXML_BEFORETAKINGTRANSITION);
	}
	virtual void afterTakingTransition(const std::string& sessionId, const XERCESC_NS::DOMElement* transition) {
		CHECK_CALLBACK_TYPE(USCXML_AFTERTAKINGTRANSITION);
	}

	virtual void beforeEnteringState(const std::string& sessionId, const std::string& stateName, const XERCESC_NS::DOMElement* state) {
		CHECK_CALLBACK_TYPE(USCXML_BEFOREENTERINGSTATE);
	}
	virtual void afterEnteringState(const std::string& sessionId, const std::string& stateName, const XERCESC_NS::DOMElement* state) {
		CHECK_CALLBACK_TYPE(USCXML_AFTERENTERINGSTATE);
	}

	virtual void beforeInvoking(const std::string& sessionId, const XERCESC_NS::DOMElement* invokeElem, const std::string& invokeid) {
		CHECK_CALLBACK_TYPE(USCXML_BEFOREINVOKING);
	}
	virtual void afterInvoking(const std::string& sessionId, const XERCESC_NS::DOMElement* invokeElem, const std::string& invokeid) {
		CHECK_CALLBACK_TYPE(USCXML_AFTERINVOKING);
	}

	virtual void afterMicroStep(const std::string& sessionId) {
		CHECK_CALLBACK_TYPE(USCXML_AFTERMICROSTEP);
	}

	virtual void onStableConfiguration(const std::string& sessionId) {
		CHECK_CALLBACK_TYPE(USCXML_ONSTABLECONFIGURATION);
	}

	virtual void beforeCompletion(const std::string& sessionId) {
		CHECK_CALLBACK_TYPE(USCXML_BEFORECOMPLETION);
	}
	virtual void afterCompletion(const std::string& sessionId) {
		CHECK_CALLBACK_TYPE(USCXML_AFTERCOMPLETION);
	}

};

int main(int argc, char** argv) {

	SequenceCheckingMonitor mon;

	int iterations = 1;

	while(iterations--) {

		if (1) {
			// syntactic xml parse error
			try {
				const char* xml = "<invalid";
				Interpreter interpreter = Interpreter::fromXML(xml, "");
				assert(false);
			} catch (Event& e) {
				std::cout << e;
			}
		}

		if (1) {
			// semantic xml parse error
			try {
				const char* xml = "<invalid />";
				Interpreter interpreter = Interpreter::fromXML(xml, "");
				interpreter.addMonitor(&mon);
				assert(interpreter.getState() == USCXML_INSTANTIATED);
				interpreter.step();
				assert(false);
			} catch (Event& e) {
				std::cout << e;
			}
		}

		if (1) {
			// request unknown datamodel
			try {
				const char* xml =
				    "<scxml datamodel=\"invalid\">"
				    "	<state id=\"start\">"
				    "		<transition target=\"done\" />"
				    " </state>"
				    " <final id=\"done\" />"
				    "</scxml>";
				Interpreter interpreter = Interpreter::fromXML(xml, "");
				interpreter.addMonitor(&mon);
				assert(interpreter.getState() == USCXML_INSTANTIATED);
				interpreter.step();
				assert(false);
			} catch (Event& e) {
				std::cout << e;
			}
		}

		if (1) {
			// two microsteps
			const char* xml =
			    "<scxml>"
			    "	<state id=\"start\">"
			    "		<transition target=\"s2\" />"
			    " </state>"
			    "	<state id=\"s2\">"
			    "		<transition target=\"done\" />"
			    " </state>"
			    " <final id=\"done\" />"
			    "</scxml>";

			Interpreter interpreter = Interpreter::fromXML(xml, "");
			interpreter.addMonitor(&mon);

			callBackSeq.push_back(USCXML_BEFOREMICROSTEP);
			callBackSeq.push_back(USCXML_BEFOREENTERINGSTATE); // scxml
			callBackSeq.push_back(USCXML_AFTERENTERINGSTATE);
			callBackSeq.push_back(USCXML_BEFOREENTERINGSTATE); // start
			callBackSeq.push_back(USCXML_AFTERENTERINGSTATE);
			callBackSeq.push_back(USCXML_AFTERMICROSTEP);

			callBackSeq.push_back(USCXML_BEFOREMICROSTEP);
			callBackSeq.push_back(USCXML_BEFOREEXITINGSTATE); // start
			callBackSeq.push_back(USCXML_AFTEREXITINGSTATE);
			callBackSeq.push_back(USCXML_BEFORETAKINGTRANSITION);
			callBackSeq.push_back(USCXML_AFTERTAKINGTRANSITION);
			callBackSeq.push_back(USCXML_BEFOREENTERINGSTATE); // s2
			callBackSeq.push_back(USCXML_AFTERENTERINGSTATE);
			callBackSeq.push_back(USCXML_AFTERMICROSTEP);

			callBackSeq.push_back(USCXML_BEFOREMICROSTEP);
			callBackSeq.push_back(USCXML_BEFOREEXITINGSTATE); // s2
			callBackSeq.push_back(USCXML_AFTEREXITINGSTATE);
			callBackSeq.push_back(USCXML_BEFORETAKINGTRANSITION);
			callBackSeq.push_back(USCXML_AFTERTAKINGTRANSITION);
			callBackSeq.push_back(USCXML_BEFOREENTERINGSTATE); // final
			callBackSeq.push_back(USCXML_AFTERENTERINGSTATE);
			callBackSeq.push_back(USCXML_AFTERMICROSTEP);

			callBackSeq.push_back(USCXML_BEFORECOMPLETION); // interpreter is finalizing
			callBackSeq.push_back(USCXML_AFTERCOMPLETION);

			assert(interpreter.getState() == USCXML_INSTANTIATED);
			assert(interpreter.step() == USCXML_INITIALIZED);
			assert(interpreter.step() == USCXML_MICROSTEPPED); // initial config
			assert(interpreter.step() == USCXML_MICROSTEPPED); // s2
			assert(interpreter.step() == USCXML_MICROSTEPPED); // done
			assert(interpreter.step() == USCXML_FINISHED); // cleaned up
			assert(callBackSeq.empty());
		}

		if (1) {
			// single macrostep, multiple runs
			const char* xml =
			    "<scxml>"
			    "	<state id=\"start\">"
			    "		<transition target=\"done\" />"
			    " </state>"
			    " <final id=\"done\" />"
			    "</scxml>";

			Interpreter interpreter = Interpreter::fromXML(xml, "");
			interpreter.addMonitor(&mon);

			callBackSeq.push_back(USCXML_BEFOREMICROSTEP);
			callBackSeq.push_back(USCXML_BEFOREENTERINGSTATE); // scxml
			callBackSeq.push_back(USCXML_AFTERENTERINGSTATE);
			callBackSeq.push_back(USCXML_BEFOREENTERINGSTATE); // start
			callBackSeq.push_back(USCXML_AFTERENTERINGSTATE);
			callBackSeq.push_back(USCXML_AFTERMICROSTEP);

			callBackSeq.push_back(USCXML_BEFOREMICROSTEP);
			callBackSeq.push_back(USCXML_BEFOREEXITINGSTATE); // start
			callBackSeq.push_back(USCXML_AFTEREXITINGSTATE);
			callBackSeq.push_back(USCXML_BEFORETAKINGTRANSITION);
			callBackSeq.push_back(USCXML_AFTERTAKINGTRANSITION);
			callBackSeq.push_back(USCXML_BEFOREENTERINGSTATE); // done
			callBackSeq.push_back(USCXML_AFTERENTERINGSTATE);
			callBackSeq.push_back(USCXML_AFTERMICROSTEP);

			callBackSeq.push_back(USCXML_BEFORECOMPLETION);
			callBackSeq.push_back(USCXML_AFTERCOMPLETION);

			assert(interpreter.getState() == USCXML_INSTANTIATED);
			assert(interpreter.step() == USCXML_INITIALIZED);
			assert(interpreter.step() == USCXML_MICROSTEPPED);
			assert(interpreter.step() == USCXML_MICROSTEPPED);
			assert(interpreter.step() == USCXML_FINISHED);
			assert(callBackSeq.empty());
			interpreter.reset();

			callBackSeq.push_back(USCXML_BEFOREMICROSTEP);
			callBackSeq.push_back(USCXML_BEFOREENTERINGSTATE); // scxml
			callBackSeq.push_back(USCXML_AFTERENTERINGSTATE);
			callBackSeq.push_back(USCXML_BEFOREENTERINGSTATE); // start
			callBackSeq.push_back(USCXML_AFTERENTERINGSTATE);
			callBackSeq.push_back(USCXML_AFTERMICROSTEP);

			callBackSeq.push_back(USCXML_BEFOREMICROSTEP);
			callBackSeq.push_back(USCXML_BEFOREEXITINGSTATE); // start
			callBackSeq.push_back(USCXML_AFTEREXITINGSTATE);
			callBackSeq.push_back(USCXML_BEFORETAKINGTRANSITION);
			callBackSeq.push_back(USCXML_AFTERTAKINGTRANSITION);
			callBackSeq.push_back(USCXML_BEFOREENTERINGSTATE); // done
			callBackSeq.push_back(USCXML_AFTERENTERINGSTATE);
			callBackSeq.push_back(USCXML_AFTERMICROSTEP);

			callBackSeq.push_back(USCXML_BEFORECOMPLETION);
			callBackSeq.push_back(USCXML_AFTERCOMPLETION);

			assert(interpreter.getState() == USCXML_INSTANTIATED);
			assert(interpreter.step() == USCXML_INITIALIZED);
			assert(interpreter.step() == USCXML_MICROSTEPPED);
			assert(interpreter.step() == USCXML_MICROSTEPPED);
			assert(interpreter.step() == USCXML_FINISHED);
		}

		if (1) {
			// macrostep in between
			const char* xml =
			    "<scxml>"
			    "	<state id=\"start\">"
			    "		<onentry>"
			    "			<send event=\"continue\" delay=\"2s\"/>"
			    "		</onentry>"
			    "		<transition target=\"s2\" event=\"continue\" />"
			    " </state>"
			    "	<state id=\"s2\">"
			    "		<transition target=\"done\" />"
			    " </state>"
			    " <final id=\"done\" />"
			    "</scxml>";

			Interpreter interpreter = Interpreter::fromXML(xml, "");
			interpreter.addMonitor(&mon);
			callBackSeq.push_back(USCXML_BEFOREMICROSTEP);
			callBackSeq.push_back(USCXML_BEFOREENTERINGSTATE); // scxml
			callBackSeq.push_back(USCXML_AFTERENTERINGSTATE);
			callBackSeq.push_back(USCXML_BEFOREENTERINGSTATE); // start
			callBackSeq.push_back(USCXML_BEFOREEXECUTINGCONTENT); // send
			callBackSeq.push_back(USCXML_AFTEREXECUTINGCONTENT);
			callBackSeq.push_back(USCXML_AFTERENTERINGSTATE);
			callBackSeq.push_back(USCXML_AFTERMICROSTEP);

			callBackSeq.push_back(USCXML_ONSTABLECONFIGURATION);
			callBackSeq.push_back(USCXML_BEFOREPROCESSINGEVENT);

			callBackSeq.push_back(USCXML_BEFOREMICROSTEP);
			callBackSeq.push_back(USCXML_BEFOREEXITINGSTATE);
			callBackSeq.push_back(USCXML_AFTEREXITINGSTATE);
			callBackSeq.push_back(USCXML_BEFORETAKINGTRANSITION);
			callBackSeq.push_back(USCXML_AFTERTAKINGTRANSITION);
			callBackSeq.push_back(USCXML_BEFOREENTERINGSTATE);
			callBackSeq.push_back(USCXML_AFTERENTERINGSTATE);
			callBackSeq.push_back(USCXML_AFTERMICROSTEP);

			callBackSeq.push_back(USCXML_BEFOREMICROSTEP);
			callBackSeq.push_back(USCXML_BEFOREEXITINGSTATE);
			callBackSeq.push_back(USCXML_AFTEREXITINGSTATE);
			callBackSeq.push_back(USCXML_BEFORETAKINGTRANSITION);
			callBackSeq.push_back(USCXML_AFTERTAKINGTRANSITION);
			callBackSeq.push_back(USCXML_BEFOREENTERINGSTATE);
			callBackSeq.push_back(USCXML_AFTERENTERINGSTATE);
			callBackSeq.push_back(USCXML_AFTERMICROSTEP);

			callBackSeq.push_back(USCXML_BEFORECOMPLETION);
			callBackSeq.push_back(USCXML_AFTERCOMPLETION);

			assert(interpreter.getState() == USCXML_INSTANTIATED);
			assert(interpreter.step() == USCXML_INITIALIZED);
			assert(interpreter.step() == USCXML_MICROSTEPPED);
			assert(interpreter.step() == USCXML_MICROSTEPPED);
			assert(interpreter.step() == USCXML_MACROSTEPPED);
			assert(interpreter.step(0) == USCXML_IDLE);
			assert(interpreter.step() == USCXML_MICROSTEPPED);
			assert(interpreter.step() == USCXML_MICROSTEPPED);
			assert(interpreter.step() == USCXML_FINISHED);
		}
	}
	return EXIT_SUCCESS;
}

max_stars_repo_name: stil/uscxml

max_issues_repo_name: stil/uscxml

max_forks_repo_name: stil/uscxml


text:
// Copyright Aleksey Gurtovoy 2001-2006
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/mpl for documentation.

// $Id$
// $Date$
// $Revision$

// NO INCLUDE GUARDS, THE HEADER IS INTENDED FOR MULTIPLE INCLUSION!

#include <boost/mpl/aux_/config/workaround.hpp>

#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/stringize.hpp>

#   define AUX778076_HEADER \
    aux_/preprocessed/plain/BOOST_MPL_PREPROCESSED_HEADER \
/**/

#if BOOST_WORKAROUND(__IBMCPP__, BOOST_TESTED_AT(700))
#   define AUX778076_INCLUDE_STRING BOOST_PP_STRINGIZE(boost/mpl/list/AUX778076_HEADER)
#   include AUX778076_INCLUDE_STRING
#   undef AUX778076_INCLUDE_STRING
#else
#   include BOOST_PP_STRINGIZE(boost/mpl/list/AUX778076_HEADER)
#endif

#   undef AUX778076_HEADER

#undef BOOST_MPL_PREPROCESSED_HEADER


text:
//
//  main.cpp
//
//  Created by Dylan Menzies on 10/11/2014.
//  Copyright (c) 2014 ISVR, University of Southampton. All rights reserved.
//

#include <libpanning/VBAP.h>
#include <libpanning/CAP.h>
#include <libpanning/AllRAD.h>
#include <boost/filesystem.hpp>

#include <boost/test/unit_test.hpp>

#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <iterator>
#include <stdexcept>
#include <vector>

BOOST_AUTO_TEST_CASE( VbapInstantiation )
{
  using namespace visr;
  using namespace visr::panning;

#if 0
  LoudspeakerArray array, regArray;
  VBAP vbap;
  AllRAD allrad;

  std::size_t numberOfSources = 8;

  std::vector<XYZ> sourcePos( numberOfSources );

  FILE* file;

  boost::filesystem::path const configDir( CMAKE_SOURCE_DIR "/config" );
  boost::filesystem::path const sourceDir( CMAKE_CURRENT_SOURCE_DIR );

  // Useage / test VBAP with 8 sources around an octahedron array

//  boost::filesystem::path bfile = configDir / boost::filesystem::path("isvr/cube_audiolab.txt");
//  boost::filesystem::path bfile = configDir / boost::filesystem::path("generic/octahedron.txt");
//  boost::filesystem::path bfile = configDir / boost::filesystem::path("isvr/9.1_audiolab.txt");

  boost::filesystem::path bfile = configDir / boost::filesystem::path( "isvr/bak/22.1_audiolab.txt" );

  file = fopen( bfile.string().c_str(), "r" );
  if( array.load( file ) == -1 )
  {
    return -1;
  }
  fclose( file );
  file = 0;

  // Alternatively, load the config file in XML format.
  boost::filesystem::path configFileXml = configDir / boost::filesystem::path( "isvr/audiolab_22speakers_1subwoofer.xml" );
  array.loadXmlFile( configFileXml.string() );

  try
  {
    vbap.setLoudspeakerArray( &array );
  }
  catch( std::invalid_argument const & e )
  {
    std::cerr << "Error while loading XML array configuration: " << e.what() << std::endl;
    return EXIT_FAILURE;
  }

{
  vbap.setListenerPosition( 0.0f, 0.0f, 0.0f );
  //    vbap.setListenerPosition(-1.9f, 0.0f, -0.1f);
  //    vbap.setListenerPosition(1.5f, 0.0f, 0.4f);
  //    vbap.setListenerPosition(-1.9f, 0.0f, +0.05f);
  //    vbap.setListenerPosition(0.0f, -0.6f, -0.2f);
  //    vbap.setListenerPosition(0.0f, -0.6f, -0.2f);  // hit triplet 39 with pw(-1,0,0)
  //    vbap.setListenerPosition(2.0f, 0.0f, 0.0f);  // hit triplet 35 with pw(0,0,-1)
  vbap.calcInvMatrices();

  sourcePos[0].set( 2.08f, 1.0f, -5.0f, true );
  //    sourcePos[0].set(-1.0f,	0.0, 0.0f, true);     // plane wave from front/back
  //    sourcePos[0].set(0.0f, -1.0f, 0.0f, true);     // plane wave from left/right
  //    sourcePos[0].set(0.0f, 0.0f, -1.0f, true);     // plane wave from below
  //    sourcePos[0].set(1.78f, 1.73f, -0.86f, false);

  //    vbap.setNumSources( numberOfSources );
  //    sourcePos[0].set(1.0, 1.0, 1.0, false);
  //    sourcePos[0].set(1.0,	0.3, -0.2, false); // for 9.1_audiolab.txt jumps between triplet 11 and 10 as z reduced
  //    sourcePos[0].set(0.0, 1.0, -0.9, false);
  sourcePos[1].set( 1.0f, 0.0f, 0.0f, false );
  sourcePos[2].set( 0.0f, 1.0f, 0.0f, false );
  sourcePos[3].set( 0.0f, 0.0f, 1.0f, false );
  sourcePos[4].set( -1.0f, 0.0f, 0.0f, false );
  sourcePos[5].set( 0.0f, -1.0f, 0.0f, false );
  sourcePos[6].set( 0.0f, 0.0f, -1.0f, false );
  sourcePos[7].set( -1.0f, -1.0f, -1.0f, false );

  vbap.setNumSources( 1 ); // This means that the output is computed only for the zeroeth source in the vector.
  vbap.setSourcePositions( &sourcePos[0] );

  vbap.calcGains();

  efl::BasicMatrix<Afloat> const & vbapGains = vbap.getGains();   // Check in watch window
  // Print the matrix.
  std::size_t const numCols = vbapGains.numberOfColumns();
  for( std::size_t rowIdx(0); rowIdx < vbapGains.numberOfRows(); ++rowIdx )
  {
    Afloat const * rowPtr = vbapGains.row( rowIdx );
    std::cout << "VBAP gain for source #" << rowIdx << ": ";
    std::copy( rowPtr, rowPtr+numCols, std::ostream_iterator<Afloat>( std::cout, ", " ) );
    std::cout << std::endl;
  }

  // 5.1 test, 2D VBAP

  // file = fopen("arrays/5.1.txt","r");
  bfile = configDir / boost::filesystem::path( "isvr/stereo_audiolab.txt" );
  //bfile = configDir / boost::filesystem::path("isvr/5.1_audiolab.txt");
  file = fopen( bfile.string().c_str(), "r" );
  if( array.load( file ) == -1 ) return -1;
  fclose( file );
  file = 0;

  vbap.setLoudspeakerArray( &array );
  vbap.setListenerPosition( 0.0, 0.0, 0.0 );
  vbap.calcInvMatrices();

  vbap.setNumSources( 4 );
  sourcePos[0].set( 1.0, 0.0, 0.0, false );
  //    sourcePos[0].set(1.0, 0.0, 0.0, true);  // plane wave
  sourcePos[1].set( 0.0, 1.0, 0.0, false );
  sourcePos[2].set( -1.0, 0.0, 0.0, false );
  sourcePos[3].set( 0.0, -1.0, 0.0, false );
  //    sourcePos[0].set(1.0, 0.0, -5.0, false);
  //    sourcePos[1].set(0.0, 1.0, -5.0, false);
  //    sourcePos[2].set(-1.0, 0.0, -5.0, false);
  //    sourcePos[3].set(0.0, -10.0, -50.0, false);

  vbap.setSourcePositions( &sourcePos[0] );

  vbap.calcGains();

  // Check the updated values of vbapGains in watch window
#endif
}