<commit_before>/*
 * Copyright © 2014 Intel Corporation
 *
 * 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 (including the next
 * paragraph) 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.
 */

#include "brw_fs.h"
#include "brw_fs_live_variables.h"
#include "brw_cfg.h"

/** @file brw_fs_cmod_propagation.cpp
 *
 * Implements a pass that propagates the conditional modifier from a CMP x 0.0
 * instruction into the instruction that generated x. For instance, in this
 * sequence
 *
 *    add(8)          g70<1>F    g69<8,8,1>F    4096F
 *    cmp.ge.f0(8)    null       g70<8,8,1>F    0F
 *
 * we can do the comparison as part of the ADD instruction directly:
 *
 *    add.ge.f0(8)    g70<1>F    g69<8,8,1>F    4096F
 *
 * If there had been a use of the flag register and another CMP using g70
 *
 *    add.ge.f0(8)    g70<1>F    g69<8,8,1>F    4096F
 *    (+f0) sel(8)    g71<F>     g72<8,8,1>F    g73<8,8,1>F
 *    cmp.ge.f0(8)    null       g70<8,8,1>F    0F
 *
 * we can recognize that the CMP is generating the flag value that already
 * exists and therefore remove the instruction.
 */

static bool
opt_cmod_propagation_local(fs_visitor *v, bblock_t *block)
{
   bool progress = false;
   int ip = block->end_ip + 1;

   foreach_inst_in_block_reverse_safe(fs_inst, inst, block) {
      ip--;

      if ((inst->opcode != BRW_OPCODE_CMP &&
           inst->opcode != BRW_OPCODE_MOV) ||
          inst->predicate != BRW_PREDICATE_NONE ||
          !inst->dst.is_null() ||
          inst->src[0].file != GRF ||
          inst->src[0].abs)
         continue;

      if (inst->opcode == BRW_OPCODE_CMP && !inst->src[1].is_zero())
         continue;

      if (inst->opcode == BRW_OPCODE_MOV &&
          (inst->conditional_mod != BRW_CONDITIONAL_NZ ||
           inst->src[0].negate))
         continue;

      bool read_flag = false;
      foreach_inst_in_block_reverse_starting_from(fs_inst, scan_inst, inst,
                                                  block) {
         if (scan_inst->overwrites_reg(inst->src[0])) {
            if (scan_inst->is_partial_write() ||
                scan_inst->dst.reg_offset != inst->src[0].reg_offset)
               break;

            if (inst->opcode == BRW_OPCODE_MOV) {
               if (!scan_inst->writes_flag())
                  break;

               inst->remove(block);
               progress = true;
               break;
            }

            enum brw_conditional_mod cond =
               inst->src[0].negate ? brw_swap_cmod(inst->conditional_mod)
                                   : inst->conditional_mod;

            if (scan_inst->can_do_cmod() &&
                ((!read_flag && scan_inst->conditional_mod == BRW_CONDITIONAL_NONE) ||
                 scan_inst->conditional_mod == cond)) {
               scan_inst->conditional_mod = cond;
               inst->remove(block);
               progress = true;
            }
            break;
         }

         if (scan_inst->writes_flag())
            break;

         read_flag = read_flag || scan_inst->reads_flag();
      }
   }

   return progress;
}

bool
fs_visitor::opt_cmod_propagation()
{
   bool progress = false;

   foreach_block_reverse(block, cfg) {
      progress = opt_cmod_propagation_local(this, block) || progress;
   }

   if (progress)
      invalidate_live_intervals();

   return progress;
}
<commit_msg>i965: Handle CMP.nz ... 0 and MOV.nz similarly in cmod propagation.<commit_after>/*
 * Copyright © 2014 Intel Corporation
 *
 * 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 (including the next
 * paragraph) 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.
 */

#include "brw_fs.h"
#include "brw_fs_live_variables.h"
#include "brw_cfg.h"

/** @file brw_fs_cmod_propagation.cpp
 *
 * Implements a pass that propagates the conditional modifier from a CMP x 0.0
 * instruction into the instruction that generated x. For instance, in this
 * sequence
 *
 *    add(8)          g70<1>F    g69<8,8,1>F    4096F
 *    cmp.ge.f0(8)    null       g70<8,8,1>F    0F
 *
 * we can do the comparison as part of the ADD instruction directly:
 *
 *    add.ge.f0(8)    g70<1>F    g69<8,8,1>F    4096F
 *
 * If there had been a use of the flag register and another CMP using g70
 *
 *    add.ge.f0(8)    g70<1>F    g69<8,8,1>F    4096F
 *    (+f0) sel(8)    g71<F>     g72<8,8,1>F    g73<8,8,1>F
 *    cmp.ge.f0(8)    null       g70<8,8,1>F    0F
 *
 * we can recognize that the CMP is generating the flag value that already
 * exists and therefore remove the instruction.
 */

static bool
opt_cmod_propagation_local(fs_visitor *v, bblock_t *block)
{
   bool progress = false;
   int ip = block->end_ip + 1;

   foreach_inst_in_block_reverse_safe(fs_inst, inst, block) {
      ip--;

      if ((inst->opcode != BRW_OPCODE_CMP &&
           inst->opcode != BRW_OPCODE_MOV) ||
          inst->predicate != BRW_PREDICATE_NONE ||
          !inst->dst.is_null() ||
          inst->src[0].file != GRF ||
          inst->src[0].abs)
         continue;

      if (inst->opcode == BRW_OPCODE_CMP && !inst->src[1].is_zero())
         continue;

      if (inst->opcode == BRW_OPCODE_MOV &&
          inst->conditional_mod != BRW_CONDITIONAL_NZ)
         continue;

      bool read_flag = false;
      foreach_inst_in_block_reverse_starting_from(fs_inst, scan_inst, inst,
                                                  block) {
         if (scan_inst->overwrites_reg(inst->src[0])) {
            if (scan_inst->is_partial_write() ||
                scan_inst->dst.reg_offset != inst->src[0].reg_offset)
               break;

            /* If the instruction generating inst's source also wrote the
             * flag, and inst is doing a simple .nz comparison, then inst
             * is redundant - the appropriate value is already in the flag
             * register.  Delete inst.
             */
            if (inst->conditional_mod == BRW_CONDITIONAL_NZ &&
                !inst->src[0].negate &&
                scan_inst->writes_flag()) {
               inst->remove(block);
               progress = true;
               break;
            }

            /* Otherwise, try propagating the conditional. */
            enum brw_conditional_mod cond =
               inst->src[0].negate ? brw_swap_cmod(inst->conditional_mod)
                                   : inst->conditional_mod;

            if (scan_inst->can_do_cmod() &&
                ((!read_flag && scan_inst->conditional_mod == BRW_CONDITIONAL_NONE) ||
                 scan_inst->conditional_mod == cond)) {
               scan_inst->conditional_mod = cond;
               inst->remove(block);
               progress = true;
            }
            break;
         }

         if (scan_inst->writes_flag())
            break;

         read_flag = read_flag || scan_inst->reads_flag();
      }
   }

   return progress;
}

bool
fs_visitor::opt_cmod_propagation()
{
   bool progress = false;

   foreach_block_reverse(block, cfg) {
      progress = opt_cmod_propagation_local(this, block) || progress;
   }

   if (progress)
      invalidate_live_intervals();

   return progress;
}
<|endoftext|>


<commit_before>/**
 * @file range_search_impl.hpp
 * @author Ryan Curtin
 *
 * Implementation of the RangeSearch class.
 */
#ifndef __MLPACK_METHODS_RANGE_SEARCH_RANGE_SEARCH_IMPL_HPP
#define __MLPACK_METHODS_RANGE_SEARCH_RANGE_SEARCH_IMPL_HPP

// Just in case it hasn't been included.
#include "range_search.hpp"

// The rules for traversal.
#include "range_search_rules.hpp"

namespace mlpack {
namespace range {

template<typename TreeType>
TreeType* BuildTree(
    typename TreeType::Mat& dataset,
    std::vector<size_t>& oldFromNew,
    typename boost::enable_if_c<
        tree::TreeTraits<TreeType>::RearrangesDataset == true, TreeType*
    >::type = 0)
{
  return new TreeType(dataset, oldFromNew);
}

//! Call the tree constructor that does not do mapping.
template<typename TreeType>
TreeType* BuildTree(
    const typename TreeType::Mat& dataset,
    const std::vector<size_t>& /* oldFromNew */,
    const typename boost::enable_if_c<
        tree::TreeTraits<TreeType>::RearrangesDataset == false, TreeType*
    >::type = 0)
{
  return new TreeType(dataset);
}

template<typename MetricType,
         typename MatType,
         template<typename TreeMetricType,
                  typename TreeStatType,
                  typename TreeMatType> class TreeType>
RangeSearch<MetricType, MatType, TreeType>::RangeSearch(
    const MatType& referenceSetIn,
    const bool naive,
    const bool singleMode,
    const MetricType metric) :
    referenceTree(naive ? NULL : BuildTree<Tree>(
        const_cast<MatType&>(referenceSetIn), oldFromNewReferences)),
    referenceSet(naive ? referenceSetIn : referenceTree->Dataset()),
    treeOwner(!naive), // If in naive mode, we are not building any trees.
    naive(naive),
    singleMode(!naive && singleMode), // Naive overrides single mode.
    metric(metric),
    baseCases(0),
    scores(0)
{
  // Nothing to do.
}

template<typename MetricType,
         typename MatType,
         template<typename TreeMetricType,
                  typename TreeStatType,
                  typename TreeMatType> class TreeType>
RangeSearch<MetricType, MatType, TreeType>::RangeSearch(
    Tree* referenceTree,
    const bool singleMode,
    const MetricType metric) :
    referenceTree(referenceTree),
    referenceSet(referenceTree->Dataset()),
    treeOwner(false),
    naive(false),
    singleMode(singleMode),
    metric(metric)
{
  // Nothing else to initialize.
}

template<typename MetricType,
         typename MatType,
         template<typename TreeMetricType,
                  typename TreeStatType,
                  typename TreeMatType> class TreeType>
RangeSearch<MetricType, MatType, TreeType>::~RangeSearch()
{
  if (treeOwner && referenceTree)
    delete referenceTree;
}

template<typename MetricType,
         typename MatType,
         template<typename TreeMetricType,
                  typename TreeStatType,
                  typename TreeMatType> class TreeType>
void RangeSearch<MetricType, MatType, TreeType>::Search(
    const MatType& querySet,
    const math::Range& range,
    std::vector<std::vector<size_t>>& neighbors,
    std::vector<std::vector<double>>& distances)
{
  Timer::Start("range_search/computing_neighbors");

  // This will hold mappings for query points, if necessary.
  std::vector<size_t> oldFromNewQueries;

  // If we have built the trees ourselves, then we will have to map all the
  // indices back to their original indices when this computation is finished.
  // To avoid extra copies, we will store the unmapped neighbors and distances
  // in a separate object.
  std::vector<std::vector<size_t>>* neighborPtr = &neighbors;
  std::vector<std::vector<double>>* distancePtr = &distances;

  // Mapping is only necessary if the tree rearranges points.
  if (tree::TreeTraits<Tree>::RearrangesDataset)
  {
    // Query indices only need to be mapped if we are building the query tree
    // ourselves.
    if (!singleMode && !naive)
      distancePtr = new std::vector<std::vector<double>>;

    // Reference indices only need to be mapped if we built the reference tree
    // ourselves.
    if (treeOwner)
      neighborPtr = new std::vector<std::vector<size_t>>;
  }

  // Resize each vector.
  neighborPtr->clear(); // Just in case there was anything in it.
  neighborPtr->resize(querySet.n_cols);
  distancePtr->clear();
  distancePtr->resize(querySet.n_cols);

  // Create the helper object for the traversal.
  typedef RangeSearchRules<MetricType, Tree> RuleType;

  // Reset counts.
  baseCases = 0;
  scores = 0;

  if (naive)
  {
    RuleType rules(referenceSet, querySet, range, *neighborPtr, *distancePtr,
        metric);

    // The naive brute-force solution.
    for (size_t i = 0; i < querySet.n_cols; ++i)
      for (size_t j = 0; j < referenceSet.n_cols; ++j)
        rules.BaseCase(i, j);

    baseCases += (querySet.n_cols * referenceSet->n_cols);
  }
  else if (singleMode)
  {
    // Create the traverser.
    RuleType rules(referenceSet, querySet, range, *neighborPtr, *distancePtr,
        metric);
    typename Tree::template SingleTreeTraverser<RuleType> traverser(rules);

    // Now have it traverse for each point.
    for (size_t i = 0; i < querySet.n_cols; ++i)
      traverser.Traverse(i, *referenceTree);

    baseCases += rules.BaseCases();
    scores += rules.Scores();
  }
  else // Dual-tree recursion.
  {
    // Build the query tree.
    Timer::Stop("range_search/computing_neighbors");
    Timer::Start("range_search/tree_building");
    Tree* queryTree = BuildTree<Tree>(const_cast<MatType&>(querySet),
        oldFromNewQueries);
    Timer::Stop("range_search/tree_building");
    Timer::Start("range_search/computing_neighbors");

    // Create the traverser.
    RuleType rules(referenceSet, queryTree->Dataset(), range, *neighborPtr,
        *distancePtr, metric);
    typename Tree::template DualTreeTraverser<RuleType> traverser(rules);

    traverser.Traverse(*queryTree, *referenceTree);

    baseCases += rules.BaseCases();
    scores += rules.Scores();

    // Clean up tree memory.
    delete queryTree;
  }

  Timer::Stop("range_search/computing_neighbors");

  // Map points back to original indices, if necessary.
  if (tree::TreeTraits<Tree>::RearrangesDataset)
  {
    if (!singleMode && !naive && treeOwner)
    {
      // We must map both query and reference indices.
      neighbors.clear();
      neighbors.resize(querySet.n_cols);
      distances.clear();
      distances.resize(querySet.n_cols);

      for (size_t i = 0; i < distances.size(); i++)
      {
        // Map distances (copy a column).
        const size_t queryMapping = oldFromNewQueries[i];
        distances[queryMapping] = (*distancePtr)[i];

        // Copy each neighbor individually, because we need to map it.
        neighbors[queryMapping].resize(distances[queryMapping].size());
        for (size_t j = 0; j < distances[queryMapping].size(); j++)
          neighbors[queryMapping][j] =
              oldFromNewReferences[(*neighborPtr)[i][j]];
      }

      // Finished with temporary objects.
      delete neighborPtr;
      delete distancePtr;
    }
    else if (!singleMode && !naive)
    {
      // We must map query indices only.
      neighbors.clear();
      neighbors.resize(querySet.n_cols);
      distances.clear();
      distances.resize(querySet.n_cols);

      for (size_t i = 0; i < distances.size(); ++i)
      {
        // Map distances and neighbors (copy a column).
        const size_t queryMapping = oldFromNewQueries[i];
        distances[queryMapping] = (*distancePtr)[i];
        neighbors[queryMapping] = (*neighborPtr)[i];
      }

      // Finished with temporary objects.
      delete neighborPtr;
      delete distancePtr;
    }
    else if (treeOwner)
    {
      // We must map reference indices only.
      neighbors.clear();
      neighbors.resize(querySet.n_cols);

      for (size_t i = 0; i < neighbors.size(); i++)
      {
        neighbors[i].resize((*neighborPtr)[i].size());
        for (size_t j = 0; j < neighbors[i].size(); j++)
          neighbors[i][j] = oldFromNewReferences[(*neighborPtr)[i][j]];
      }

      // Finished with temporary object.
      delete neighborPtr;
    }
  }
}

template<typename MetricType,
         typename MatType,
         template<typename TreeMetricType,
                  typename TreeStatType,
                  typename TreeMatType> class TreeType>
void RangeSearch<MetricType, MatType, TreeType>::Search(
    Tree* queryTree,
    const math::Range& range,
    std::vector<std::vector<size_t>>& neighbors,
    std::vector<std::vector<double>>& distances)
{
  Timer::Start("range_search/computing_neighbors");

  // Get a reference to the query set.
  const MatType& querySet = queryTree->Dataset();

  // Make sure we are in dual-tree mode.
  if (singleMode || naive)
    throw std::invalid_argument("cannot call RangeSearch::Search() with a "
        "query tree when naive or singleMode are set to true");

  // We won't need to map query indices, but will we need to map distances?
  std::vector<std::vector<size_t>>* neighborPtr = &neighbors;

  if (treeOwner && tree::TreeTraits<Tree>::RearrangesDataset)
    neighborPtr = new std::vector<std::vector<size_t>>;

  // Resize each vector.
  neighborPtr->clear(); // Just in case there was anything in it.
  neighborPtr->resize(querySet.n_cols);
  distances.clear();
  distances.resize(querySet.n_cols);

  // Create the helper object for the traversal.
  typedef RangeSearchRules<MetricType, Tree> RuleType;
  RuleType rules(referenceSet, queryTree->Dataset(), range, *neighborPtr,
      distances, metric);

  // Create the traverser.
  typename Tree::template DualTreeTraverser<RuleType> traverser(rules);

  traverser.Traverse(*queryTree, *referenceTree);

  Timer::Stop("range_search/computing_neighbors");

  baseCases = rules.BaseCases();
  scores = rules.Scores();

  // Do we need to map indices?
  if (treeOwner && tree::TreeTraits<Tree>::RearrangesDataset)
  {
    // We must map reference indices only.
    neighbors.clear();
    neighbors.resize(querySet.n_cols);

    for (size_t i = 0; i < neighbors.size(); i++)
    {
      neighbors[i].resize((*neighborPtr)[i].size());
      for (size_t j = 0; j < neighbors[i].size(); j++)
        neighbors[i][j] = oldFromNewReferences[(*neighborPtr)[i][j]];
    }

    // Finished with temporary object.
    delete neighborPtr;
  }
}

template<typename MetricType,
         typename MatType,
         template<typename TreeMetricType,
                  typename TreeStatType,
                  typename TreeMatType> class TreeType>
void RangeSearch<MetricType, MatType, TreeType>::Search(
    const math::Range& range,
    std::vector<std::vector<size_t>>& neighbors,
    std::vector<std::vector<double>>& distances)
{
  Timer::Start("range_search/computing_neighbors");

  // Here, we will use the query set as the reference set.
  std::vector<std::vector<size_t>>* neighborPtr = &neighbors;
  std::vector<std::vector<double>>* distancePtr = &distances;

  if (tree::TreeTraits<Tree>::RearrangesDataset && treeOwner)
  {
    // We will always need to rearrange in this case.
    distancePtr = new std::vector<std::vector<double>>;
    neighborPtr = new std::vector<std::vector<size_t>>;
  }

  // Resize each vector.
  neighborPtr->clear(); // Just in case there was anything in it.
  neighborPtr->resize(referenceSet.n_cols);
  distancePtr->clear();
  distancePtr->resize(referenceSet.n_cols);

  // Create the helper object for the traversal.
  typedef RangeSearchRules<MetricType, Tree> RuleType;
  RuleType rules(referenceSet, referenceSet, range, *neighborPtr, *distancePtr,
      metric, true /* don't return the query point in the results */);

  if (naive)
  {
    // The naive brute-force solution.
    for (size_t i = 0; i < referenceSet.n_cols; ++i)
      for (size_t j = 0; j < referenceSet.n_cols; ++j)
        rules.BaseCase(i, j);
  }
  else if (singleMode)
  {
    // Create the traverser.
    typename Tree::template SingleTreeTraverser<RuleType> traverser(rules);

    // Now have it traverse for each point.
    for (size_t i = 0; i < referenceSet.n_cols; ++i)
      traverser.Traverse(i, *referenceTree);

    baseCases = rules.BaseCases();
    scores = rules.Scores();
  }
  else // Dual-tree recursion.
  {
    // Create the traverser.
    typename Tree::template DualTreeTraverser<RuleType> traverser(rules);

    traverser.Traverse(*referenceTree, *referenceTree);

    baseCases = rules.BaseCases();
    scores = rules.Scores();
  }

  Timer::Stop("range_search/computing_neighbors");

  // Do we need to map the reference indices?
  if (treeOwner && tree::TreeTraits<Tree>::RearrangesDataset)
  {
    neighbors.clear();
    neighbors.resize(referenceSet.n_cols);
    distances.clear();
    distances.resize(referenceSet.n_cols);

    for (size_t i = 0; i < distances.size(); i++)
    {
      // Map distances (copy a column).
      const size_t refMapping = oldFromNewReferences[i];
      distances[refMapping] = (*distancePtr)[i];

      // Copy each neighbor individually, because we need to map it.
      neighbors[refMapping].resize(distances[refMapping].size());
      for (size_t j = 0; j < distances[refMapping].size(); j++)
      {
        neighbors[refMapping][j] = oldFromNewReferences[(*neighborPtr)[i][j]];
      }
    }

    // Finished with temporary objects.
    delete neighborPtr;
    delete distancePtr;
  }
}

template<typename MetricType,
         typename MatType,
         template<typename TreeMetricType,
                  typename TreeStatType,
                  typename TreeMatType> class TreeType>
std::string RangeSearch<MetricType, MatType, TreeType>::ToString() const
{
  std::ostringstream convert;
  convert << "Range Search  [" << this << "]" << std::endl;
  if (treeOwner)
    convert << "  Tree Owner: TRUE" << std::endl;
  if (naive)
    convert << "  Naive: TRUE" << std::endl;
  convert << "  Metric: " << std::endl <<
      mlpack::util::Indent(metric.ToString(),2);
  return convert.str();
}

} // namespace range
} // namespace mlpack

#endif
<commit_msg>Initialize baseCases and scores correctly.<commit_after>/**
 * @file range_search_impl.hpp
 * @author Ryan Curtin
 *
 * Implementation of the RangeSearch class.
 */
#ifndef __MLPACK_METHODS_RANGE_SEARCH_RANGE_SEARCH_IMPL_HPP
#define __MLPACK_METHODS_RANGE_SEARCH_RANGE_SEARCH_IMPL_HPP

// Just in case it hasn't been included.
#include "range_search.hpp"

// The rules for traversal.
#include "range_search_rules.hpp"

namespace mlpack {
namespace range {

template<typename TreeType>
TreeType* BuildTree(
    typename TreeType::Mat& dataset,
    std::vector<size_t>& oldFromNew,
    typename boost::enable_if_c<
        tree::TreeTraits<TreeType>::RearrangesDataset == true, TreeType*
    >::type = 0)
{
  return new TreeType(dataset, oldFromNew);
}

//! Call the tree constructor that does not do mapping.
template<typename TreeType>
TreeType* BuildTree(
    const typename TreeType::Mat& dataset,
    const std::vector<size_t>& /* oldFromNew */,
    const typename boost::enable_if_c<
        tree::TreeTraits<TreeType>::RearrangesDataset == false, TreeType*
    >::type = 0)
{
  return new TreeType(dataset);
}

template<typename MetricType,
         typename MatType,
         template<typename TreeMetricType,
                  typename TreeStatType,
                  typename TreeMatType> class TreeType>
RangeSearch<MetricType, MatType, TreeType>::RangeSearch(
    const MatType& referenceSetIn,
    const bool naive,
    const bool singleMode,
    const MetricType metric) :
    referenceTree(naive ? NULL : BuildTree<Tree>(
        const_cast<MatType&>(referenceSetIn), oldFromNewReferences)),
    referenceSet(naive ? referenceSetIn : referenceTree->Dataset()),
    treeOwner(!naive), // If in naive mode, we are not building any trees.
    naive(naive),
    singleMode(!naive && singleMode), // Naive overrides single mode.
    metric(metric),
    baseCases(0),
    scores(0)
{
  // Nothing to do.
}

template<typename MetricType,
         typename MatType,
         template<typename TreeMetricType,
                  typename TreeStatType,
                  typename TreeMatType> class TreeType>
RangeSearch<MetricType, MatType, TreeType>::RangeSearch(
    Tree* referenceTree,
    const bool singleMode,
    const MetricType metric) :
    referenceTree(referenceTree),
    referenceSet(referenceTree->Dataset()),
    treeOwner(false),
    naive(false),
    singleMode(singleMode),
    metric(metric),
    baseCases(0),
    scores(0)
{
  // Nothing else to initialize.
}

template<typename MetricType,
         typename MatType,
         template<typename TreeMetricType,
                  typename TreeStatType,
                  typename TreeMatType> class TreeType>
RangeSearch<MetricType, MatType, TreeType>::~RangeSearch()
{
  if (treeOwner && referenceTree)
    delete referenceTree;
}

template<typename MetricType,
         typename MatType,
         template<typename TreeMetricType,
                  typename TreeStatType,
                  typename TreeMatType> class TreeType>
void RangeSearch<MetricType, MatType, TreeType>::Search(
    const MatType& querySet,
    const math::Range& range,
    std::vector<std::vector<size_t>>& neighbors,
    std::vector<std::vector<double>>& distances)
{
  Timer::Start("range_search/computing_neighbors");

  // This will hold mappings for query points, if necessary.
  std::vector<size_t> oldFromNewQueries;

  // If we have built the trees ourselves, then we will have to map all the
  // indices back to their original indices when this computation is finished.
  // To avoid extra copies, we will store the unmapped neighbors and distances
  // in a separate object.
  std::vector<std::vector<size_t>>* neighborPtr = &neighbors;
  std::vector<std::vector<double>>* distancePtr = &distances;

  // Mapping is only necessary if the tree rearranges points.
  if (tree::TreeTraits<Tree>::RearrangesDataset)
  {
    // Query indices only need to be mapped if we are building the query tree
    // ourselves.
    if (!singleMode && !naive)
      distancePtr = new std::vector<std::vector<double>>;

    // Reference indices only need to be mapped if we built the reference tree
    // ourselves.
    if (treeOwner)
      neighborPtr = new std::vector<std::vector<size_t>>;
  }

  // Resize each vector.
  neighborPtr->clear(); // Just in case there was anything in it.
  neighborPtr->resize(querySet.n_cols);
  distancePtr->clear();
  distancePtr->resize(querySet.n_cols);

  // Create the helper object for the traversal.
  typedef RangeSearchRules<MetricType, Tree> RuleType;

  // Reset counts.
  baseCases = 0;
  scores = 0;

  if (naive)
  {
    RuleType rules(referenceSet, querySet, range, *neighborPtr, *distancePtr,
        metric);

    // The naive brute-force solution.
    for (size_t i = 0; i < querySet.n_cols; ++i)
      for (size_t j = 0; j < referenceSet.n_cols; ++j)
        rules.BaseCase(i, j);

    baseCases += (querySet.n_cols * referenceSet->n_cols);
  }
  else if (singleMode)
  {
    // Create the traverser.
    RuleType rules(referenceSet, querySet, range, *neighborPtr, *distancePtr,
        metric);
    typename Tree::template SingleTreeTraverser<RuleType> traverser(rules);

    // Now have it traverse for each point.
    for (size_t i = 0; i < querySet.n_cols; ++i)
      traverser.Traverse(i, *referenceTree);

    baseCases += rules.BaseCases();
    scores += rules.Scores();
  }
  else // Dual-tree recursion.
  {
    // Build the query tree.
    Timer::Stop("range_search/computing_neighbors");
    Timer::Start("range_search/tree_building");
    Tree* queryTree = BuildTree<Tree>(const_cast<MatType&>(querySet),
        oldFromNewQueries);
    Timer::Stop("range_search/tree_building");
    Timer::Start("range_search/computing_neighbors");

    // Create the traverser.
    RuleType rules(referenceSet, queryTree->Dataset(), range, *neighborPtr,
        *distancePtr, metric);
    typename Tree::template DualTreeTraverser<RuleType> traverser(rules);

    traverser.Traverse(*queryTree, *referenceTree);

    baseCases += rules.BaseCases();
    scores += rules.Scores();

    // Clean up tree memory.
    delete queryTree;
  }

  Timer::Stop("range_search/computing_neighbors");

  // Map points back to original indices, if necessary.
  if (tree::TreeTraits<Tree>::RearrangesDataset)
  {
    if (!singleMode && !naive && treeOwner)
    {
      // We must map both query and reference indices.
      neighbors.clear();
      neighbors.resize(querySet.n_cols);
      distances.clear();
      distances.resize(querySet.n_cols);

      for (size_t i = 0; i < distances.size(); i++)
      {
        // Map distances (copy a column).
        const size_t queryMapping = oldFromNewQueries[i];
        distances[queryMapping] = (*distancePtr)[i];

        // Copy each neighbor individually, because we need to map it.
        neighbors[queryMapping].resize(distances[queryMapping].size());
        for (size_t j = 0; j < distances[queryMapping].size(); j++)
          neighbors[queryMapping][j] =
              oldFromNewReferences[(*neighborPtr)[i][j]];
      }

      // Finished with temporary objects.
      delete neighborPtr;
      delete distancePtr;
    }
    else if (!singleMode && !naive)
    {
      // We must map query indices only.
      neighbors.clear();
      neighbors.resize(querySet.n_cols);
      distances.clear();
      distances.resize(querySet.n_cols);

      for (size_t i = 0; i < distances.size(); ++i)
      {
        // Map distances and neighbors (copy a column).
        const size_t queryMapping = oldFromNewQueries[i];
        distances[queryMapping] = (*distancePtr)[i];
        neighbors[queryMapping] = (*neighborPtr)[i];
      }

      // Finished with temporary objects.
      delete neighborPtr;
      delete distancePtr;
    }
    else if (treeOwner)
    {
      // We must map reference indices only.
      neighbors.clear();
      neighbors.resize(querySet.n_cols);

      for (size_t i = 0; i < neighbors.size(); i++)
      {
        neighbors[i].resize((*neighborPtr)[i].size());
        for (size_t j = 0; j < neighbors[i].size(); j++)
          neighbors[i][j] = oldFromNewReferences[(*neighborPtr)[i][j]];
      }

      // Finished with temporary object.
      delete neighborPtr;
    }
  }
}

template<typename MetricType,
         typename MatType,
         template<typename TreeMetricType,
                  typename TreeStatType,
                  typename TreeMatType> class TreeType>
void RangeSearch<MetricType, MatType, TreeType>::Search(
    Tree* queryTree,
    const math::Range& range,
    std::vector<std::vector<size_t>>& neighbors,
    std::vector<std::vector<double>>& distances)
{
  Timer::Start("range_search/computing_neighbors");

  // Get a reference to the query set.
  const MatType& querySet = queryTree->Dataset();

  // Make sure we are in dual-tree mode.
  if (singleMode || naive)
    throw std::invalid_argument("cannot call RangeSearch::Search() with a "
        "query tree when naive or singleMode are set to true");

  // We won't need to map query indices, but will we need to map distances?
  std::vector<std::vector<size_t>>* neighborPtr = &neighbors;

  if (treeOwner && tree::TreeTraits<Tree>::RearrangesDataset)
    neighborPtr = new std::vector<std::vector<size_t>>;

  // Resize each vector.
  neighborPtr->clear(); // Just in case there was anything in it.
  neighborPtr->resize(querySet.n_cols);
  distances.clear();
  distances.resize(querySet.n_cols);

  // Create the helper object for the traversal.
  typedef RangeSearchRules<MetricType, Tree> RuleType;
  RuleType rules(referenceSet, queryTree->Dataset(), range, *neighborPtr,
      distances, metric);

  // Create the traverser.
  typename Tree::template DualTreeTraverser<RuleType> traverser(rules);

  traverser.Traverse(*queryTree, *referenceTree);

  Timer::Stop("range_search/computing_neighbors");

  baseCases = rules.BaseCases();
  scores = rules.Scores();

  // Do we need to map indices?
  if (treeOwner && tree::TreeTraits<Tree>::RearrangesDataset)
  {
    // We must map reference indices only.
    neighbors.clear();
    neighbors.resize(querySet.n_cols);

    for (size_t i = 0; i < neighbors.size(); i++)
    {
      neighbors[i].resize((*neighborPtr)[i].size());
      for (size_t j = 0; j < neighbors[i].size(); j++)
        neighbors[i][j] = oldFromNewReferences[(*neighborPtr)[i][j]];
    }

    // Finished with temporary object.
    delete neighborPtr;
  }
}

template<typename MetricType,
         typename MatType,
         template<typename TreeMetricType,
                  typename TreeStatType,
                  typename TreeMatType> class TreeType>
void RangeSearch<MetricType, MatType, TreeType>::Search(
    const math::Range& range,
    std::vector<std::vector<size_t>>& neighbors,
    std::vector<std::vector<double>>& distances)
{
  Timer::Start("range_search/computing_neighbors");

  // Here, we will use the query set as the reference set.
  std::vector<std::vector<size_t>>* neighborPtr = &neighbors;
  std::vector<std::vector<double>>* distancePtr = &distances;

  if (tree::TreeTraits<Tree>::RearrangesDataset && treeOwner)
  {
    // We will always need to rearrange in this case.
    distancePtr = new std::vector<std::vector<double>>;
    neighborPtr = new std::vector<std::vector<size_t>>;
  }

  // Resize each vector.
  neighborPtr->clear(); // Just in case there was anything in it.
  neighborPtr->resize(referenceSet.n_cols);
  distancePtr->clear();
  distancePtr->resize(referenceSet.n_cols);

  // Create the helper object for the traversal.
  typedef RangeSearchRules<MetricType, Tree> RuleType;
  RuleType rules(referenceSet, referenceSet, range, *neighborPtr, *distancePtr,
      metric, true /* don't return the query point in the results */);

  if (naive)
  {
    // The naive brute-force solution.
    for (size_t i = 0; i < referenceSet.n_cols; ++i)
      for (size_t j = 0; j < referenceSet.n_cols; ++j)
        rules.BaseCase(i, j);
  }
  else if (singleMode)
  {
    // Create the traverser.
    typename Tree::template SingleTreeTraverser<RuleType> traverser(rules);

    // Now have it traverse for each point.
    for (size_t i = 0; i < referenceSet.n_cols; ++i)
      traverser.Traverse(i, *referenceTree);

    baseCases = rules.BaseCases();
    scores = rules.Scores();
  }
  else // Dual-tree recursion.
  {
    // Create the traverser.
    typename Tree::template DualTreeTraverser<RuleType> traverser(rules);

    traverser.Traverse(*referenceTree, *referenceTree);

    baseCases = rules.BaseCases();
    scores = rules.Scores();
  }

  Timer::Stop("range_search/computing_neighbors");

  // Do we need to map the reference indices?
  if (treeOwner && tree::TreeTraits<Tree>::RearrangesDataset)
  {
    neighbors.clear();
    neighbors.resize(referenceSet.n_cols);
    distances.clear();
    distances.resize(referenceSet.n_cols);

    for (size_t i = 0; i < distances.size(); i++)
    {
      // Map distances (copy a column).
      const size_t refMapping = oldFromNewReferences[i];
      distances[refMapping] = (*distancePtr)[i];

      // Copy each neighbor individually, because we need to map it.
      neighbors[refMapping].resize(distances[refMapping].size());
      for (size_t j = 0; j < distances[refMapping].size(); j++)
      {
        neighbors[refMapping][j] = oldFromNewReferences[(*neighborPtr)[i][j]];
      }
    }

    // Finished with temporary objects.
    delete neighborPtr;
    delete distancePtr;
  }
}

template<typename MetricType,
         typename MatType,
         template<typename TreeMetricType,
                  typename TreeStatType,
                  typename TreeMatType> class TreeType>
std::string RangeSearch<MetricType, MatType, TreeType>::ToString() const
{
  std::ostringstream convert;
  convert << "Range Search  [" << this << "]" << std::endl;
  if (treeOwner)
    convert << "  Tree Owner: TRUE" << std::endl;
  if (naive)
    convert << "  Naive: TRUE" << std::endl;
  convert << "  Metric: " << std::endl <<
      mlpack::util::Indent(metric.ToString(),2);
  return convert.str();
}

} // namespace range
} // namespace mlpack

#endif
<|endoftext|>


<commit_before>/*  Copyright (C) 2006 Imperial College London and others.

    Please see the AUTHORS file in the main source directory for a full list
    of copyright holders.

    Prof. C Pain
    Applied Modelling and Computation Group
    Department of Earth Science and Engineering
    Imperial College London

    C.Pain@Imperial.ac.uk

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation,
    version 2.1 of the License.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
    USA
*/

#include <cstring>
#include <iostream>
#include <stdlib.h>

#include "confdefs.h"

#include "c++debug.h"

#ifdef HAVE_MPI
#include <mpi.h>
#endif

using namespace std;

extern "C"{
#define pseudo_mesh F77_FUNC(pseudo_mesh, PSEUDO_MESH)
  void pseudo_mesh(const char* filename, const int* filename_len, const int* target_elements);
}

void Usage(){
  cout << "Usage: pseudo_mesh TRIANGLE_BASENAME\n"
       << "\n"
       << "Generates a new mesh with approximately the same local nodal density as the\n"
       << "input mesh\n"
       << "\n"
       << "Options:\n"
       << "\n"
       << "-h\t\tDisplay this help\n"
       << "-t\t\tLimit the adaptivity metric to target the same number of\n"
       <<   "\t\telements in the pseudo mesh as in the target mesh\n"
       << "-v\t\tVerbose mode" << endl;
}

int main(int argc, char** argv){
#ifdef HAVE_MPI
  MPI::Init(argc, argv);
  // Undo some MPI init shenanigans
  chdir(getenv("PWD"));
#endif

  if(argc < 2){
    Usage();
    return -1;
  }

  // Modified version of flredecomp argument parsing
  // Get any command line arguments
  // Reset optarg so we can detect changes
  optarg = NULL;
  char c;
  map<char, string> args;
  while((c = getopt(argc, argv, "htv")) != -1){
    if (c != '?'){
      if(optarg == NULL){
        args[c] = "true";
      }else{
        args[c] = optarg;
      }
    }else{
      if(isprint(optopt)){
        cerr << "Unknown option " << optopt << endl;
      }else{
        cerr << "Unknown option " << hex << optopt << endl;
      }
      Usage();
      exit(-1);
    }
  }

  // Help
  if(args.count('h')){
    Usage();
    exit(0);
  }

  // Verbosity
  int verbosity = 0;
  if(args.count('v') > 0){
    verbosity = 3;
  }
  set_global_debug_level_fc(&verbosity);

  int target_elements;
  target_elements = args.count('t') > 0 ? 1 : 0;

  int filename_len = strlen(argv[optind]);
  pseudo_mesh(argv[optind], &filename_len, &target_elements);

#ifdef HAVE_MPI
  MPI::Finalize();
#endif
  return 0;
}
<commit_msg>Avoid a seg fault on invalid input<commit_after>/*  Copyright (C) 2006 Imperial College London and others.

    Please see the AUTHORS file in the main source directory for a full list
    of copyright holders.

    Prof. C Pain
    Applied Modelling and Computation Group
    Department of Earth Science and Engineering
    Imperial College London

    C.Pain@Imperial.ac.uk

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation,
    version 2.1 of the License.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
    USA
*/

#include <cstring>
#include <iostream>
#include <stdlib.h>

#include "confdefs.h"

#include "c++debug.h"

#ifdef HAVE_MPI
#include <mpi.h>
#endif

using namespace std;

extern "C"{
#define pseudo_mesh F77_FUNC(pseudo_mesh, PSEUDO_MESH)
  void pseudo_mesh(const char* filename, const int* filename_len, const int* target_elements);
}

void Usage(){
  cout << "Usage: pseudo_mesh TRIANGLE_BASENAME\n"
       << "\n"
       << "Generates a new mesh with approximately the same local nodal density as the\n"
       << "input mesh\n"
       << "\n"
       << "Options:\n"
       << "\n"
       << "-h\t\tDisplay this help\n"
       << "-t\t\tLimit the adaptivity metric to target the same number of\n"
       <<   "\t\telements in the pseudo mesh as in the target mesh\n"
       << "-v\t\tVerbose mode" << endl;
}

int main(int argc, char** argv){
#ifdef HAVE_MPI
  MPI::Init(argc, argv);
  // Undo some MPI init shenanigans
  chdir(getenv("PWD"));
#endif

  if(argc < 2){
    Usage();
    return -1;
  }

  // Modified version of flredecomp argument parsing
  // Get any command line arguments
  // Reset optarg so we can detect changes
  optarg = NULL;
  char c;
  map<char, string> args;
  while((c = getopt(argc, argv, "htv")) != -1){
    if (c != '?'){
      if(optarg == NULL){
        args[c] = "true";
      }else{
        args[c] = optarg;
      }
    }else{
      if(isprint(optopt)){
        cerr << "Unknown option " << optopt << endl;
      }else{
        cerr << "Unknown option " << hex << optopt << endl;
      }
      Usage();
      exit(-1);
    }
  }

  // Help
  if(args.count('h')){
    Usage();
    exit(0);
  }

  if (optind != argc - 1){
    cerr << "Need exactly one non-option argument" << endl;
    Usage();
    exit(-1);
  }

  // Verbosity
  int verbosity = 0;
  if(args.count('v') > 0){
    verbosity = 3;
  }
  set_global_debug_level_fc(&verbosity);

  int target_elements;
  target_elements = args.count('t') > 0 ? 1 : 0;

  int filename_len = strlen(argv[optind]);
  pseudo_mesh(argv[optind], &filename_len, &target_elements);

#ifdef HAVE_MPI
  MPI::Finalize();
#endif
  return 0;
}
<|endoftext|>


<commit_before>/*
* This source file is part of ArkGameFrame
* For the latest info, see https://github.com/ArkGame
*
* Copyright (c) 2013-2018 ArkGame authors.
*
* 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.
*
*/

#pragma once

#include "SDK/Core/AFMacros.hpp"

template <typename TD, bool NEEDSMART>
struct MapSmartPtrType
{
    typedef TD* VALUE;
};

template <typename TD>
struct MapSmartPtrType<TD, true>
{
    typedef ARK_SHARE_PTR<TD> VALUE;
};

template <typename TD>
struct MapSmartPtrType<TD, false>
{
    typedef TD* VALUE;
};

template <typename T, typename TD, bool NEEDSMART>
class AFMapBase
{
public:
    typedef typename MapSmartPtrType<TD, NEEDSMART>::VALUE PTRTYPE;
    typedef std::map<T, PTRTYPE > MAP_DATA;
    AFMapBase()
    {
        mNullPtr = nullptr;
    }

    virtual ~AFMapBase() = default;

    virtual bool AddElement(const T& name, const PTRTYPE data)
    {
        typename MAP_DATA::iterator iter = mxObjectList.find(name);

        if (iter == mxObjectList.end())
        {
            mxObjectList.insert(typename MAP_DATA::value_type(name, data));
            return true;
        }

        return false;
    }

    virtual bool SetElement(const T& name, const PTRTYPE data)
    {
        mxObjectList[name] = data;
        return true;
    }

    virtual bool RemoveElement(const T& name)
    {
        typename MAP_DATA::iterator iter = mxObjectList.find(name);

        if (iter != mxObjectList.end())
        {
            mxObjectList.erase(iter);

            return true;
        }

        return false;
    }

    virtual const PTRTYPE& GetElement(const T& name)
    {
        typename MAP_DATA::iterator iter = mxObjectList.find(name);

        if (iter != mxObjectList.end())
        {
            return iter->second;
        }
        else
        {
            return mNullPtr;
        }
    }

    virtual const PTRTYPE& First()
    {
        if (mxObjectList.size() <= 0)
        {
            return mNullPtr;
        }

        mxObjectCurIter = mxObjectList.begin();

        if (mxObjectCurIter != mxObjectList.end())
        {
            return mxObjectCurIter->second;
        }
        else
        {
            return mNullPtr;
        }
    }

    virtual const PTRTYPE&  Next()
    {
        if (mxObjectCurIter == mxObjectList.end())
        {
            return mNullPtr;
        }

        ++mxObjectCurIter;

        if (mxObjectCurIter != mxObjectList.end())
        {
            return mxObjectCurIter->second;
        }
        else
        {
            return mNullPtr;
        }
    }

    virtual const PTRTYPE& First(T& name)
    {
        if (mxObjectList.size() <= 0)
        {
            return mNullPtr;
        }

        mxObjectCurIter = mxObjectList.begin();

        if (mxObjectCurIter != mxObjectList.end())
        {
            name = mxObjectCurIter->first;
            return mxObjectCurIter->second;
        }
        else
        {
            return mNullPtr;
        }
    }
    virtual const PTRTYPE&  Next(T& name)
    {
        if (mxObjectCurIter == mxObjectList.end())
        {
            return mNullPtr;
        }

        mxObjectCurIter++;

        if (mxObjectCurIter != mxObjectList.end())
        {
            name = mxObjectCurIter->first;
            return mxObjectCurIter->second;
        }
        else
        {
            return mNullPtr;
        }
    }

    int GetCount()
    {
        return (int)mxObjectList.size();
    }

    bool ClearAll()
    {
        mxObjectList.clear();
        return true;
    }

    bool Begin()
    {
        mxObjectCurIter = mxObjectList.begin();

        return mxObjectCurIter != mxObjectList.end();
    }

    bool Increase()
    {
        if (mxObjectCurIter != mxObjectList.end())
        {
            ++mxObjectCurIter;

            if (mxObjectCurIter != mxObjectList.end())
            {
                return true;
            }
        }

        return false;
    }

    const PTRTYPE& GetCurrentData()
    {
        if (mxObjectCurIter != mxObjectList.end())
        {
            return mxObjectCurIter->second;
        }
        else
        {
            return mNullPtr;
        }
    }

private:
    MAP_DATA mxObjectList;
    typename MAP_DATA::iterator mxObjectCurIter;
    PTRTYPE mNullPtr;
};

template <typename T, typename TD>
class AFMapEx: public AFMapBase<T, TD, true >
{
};

template <typename T, typename TD>
class AFMap: public AFMapBase<T, TD, false >
{
};
<commit_msg>test sonarcloud<commit_after>/*
* This source file is part of ArkGameFrame
* For the latest info, see https://github.com/ArkGame
*
* Copyright (c) 2013-2018 ArkGame authors.
*
* 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.
*
*/

#pragma once

#include "SDK/Core/AFMacros.hpp"

template <typename TD, bool NEEDSMART>
struct MapSmartPtrType
{
    typedef TD* VALUE;
};

template <typename TD>
struct MapSmartPtrType<TD, true>
{
    typedef ARK_SHARE_PTR<TD> VALUE;
};

template <typename TD>
struct MapSmartPtrType<TD, false>
{
    typedef TD* VALUE;
};

template <typename T, typename TD, bool NEEDSMART>
class AFMapBase
{
public:
    typedef typename MapSmartPtrType<TD, NEEDSMART>::VALUE PTRTYPE;
    typedef std::map<T, PTRTYPE > MAP_DATA;
    AFMapBase()
    {
        mNullPtr = nullptr;
    }

    virtual ~AFMapBase() = default;

    virtual bool AddElement(const T& name, const PTRTYPE data)
    {
        typename MAP_DATA::iterator iter = mxObjectList.find(name);

        if (iter == mxObjectList.end())
        {
            mxObjectList.insert(typename MAP_DATA::value_type(name, data));
            return true;
        }

        return false;
    }

    virtual bool SetElement(const T& name, const PTRTYPE data)
    {
        mxObjectList[name] = data;
        return true;
    }

    virtual bool RemoveElement(const T& name)
    {
        typename MAP_DATA::iterator iter = mxObjectList.find(name);

        if (iter != mxObjectList.end())
        {
            mxObjectList.erase(iter);

            return true;
        }

        return false;
    }

    virtual const PTRTYPE& GetElement(const T& name)
    {
        typename MAP_DATA::iterator iter = mxObjectList.find(name);

        if (iter != mxObjectList.end())
        {
            return iter->second;
        }
        else
        {
            return mNullPtr;
        }
    }

    virtual const PTRTYPE& First()
    {
        if (mxObjectList.size() <= 0)
        {
            return mNullPtr;
        }

        mxObjectCurIter = mxObjectList.begin();

        if (mxObjectCurIter != mxObjectList.end())
        {
            return mxObjectCurIter->second;
        }
        else
        {
            return mNullPtr;
        }
    }

    virtual const PTRTYPE&  Next()
    {
        if (mxObjectCurIter == mxObjectList.end())
        {
            return mNullPtr;
        }

        ++mxObjectCurIter;

        if (mxObjectCurIter != mxObjectList.end())
        {
            return mxObjectCurIter->second;
        }
        else
        {
            return mNullPtr;
        }
    }

    virtual const PTRTYPE& First(T& name)
    {
        if (mxObjectList.size() <= 0)
        {
            return mNullPtr;
        }

        mxObjectCurIter = mxObjectList.begin();

        if (mxObjectCurIter != mxObjectList.end())
        {
            name = mxObjectCurIter->first;
            return mxObjectCurIter->second;
        }
        else
        {
            return mNullPtr;
        }
    }
    virtual const PTRTYPE&  Next(T& name)
    {
        if (mxObjectCurIter == mxObjectList.end())
        {
            return mNullPtr;
        }

        mxObjectCurIter++;

        if (mxObjectCurIter != mxObjectList.end())
        {
            name = mxObjectCurIter->first;
            return mxObjectCurIter->second;
        }
        else
        {
            return mNullPtr;
        }
    }

    int GetCount()
    {
        return (int)mxObjectList.size();
    }

    bool ClearAll()
    {
        mxObjectList.clear();
        return true;
    }

    bool Begin()
    {
        mxObjectCurIter = mxObjectList.begin();

        return mxObjectCurIter != mxObjectList.end();
    }

    bool Increase()
    {
        if (mxObjectCurIter != mxObjectList.end())
        {
            ++mxObjectCurIter;

            if (mxObjectCurIter != mxObjectList.end())
            {
                return true;
            }
        }

        return false;
    }

    const PTRTYPE& GetCurrentData()
    {
        if (mxObjectCurIter != mxObjectList.end())
        {
            return mxObjectCurIter->second;
        }
        else
        {
            return mNullPtr;
        }
    }

private:
    MAP_DATA mxObjectList;
    typename MAP_DATA::iterator mxObjectCurIter;
    PTRTYPE mNullPtr;
};

template <typename T, typename TD>
class AFMapEx: public AFMapBase<T, TD, true >
{
};

template <typename T, typename TD>
class AFMap: public AFMapBase<T, TD, false >
{
};
<|endoftext|>


<commit_before>#include <iostream>
#include <algorithm>
#include <cassert>
using namespace std;

// 大域変数
const int T = 9; // 全ターン数
const int P = 4; // プレイヤー数
const int N = 6; // プログラミングの言語数
const int maxpt = 6;
const int minpt = 3;
const int wdays = 5;
const int hdays = 2;
int A[N]; // 言語の注目数
int priority[N];
/*
   priority[0] 取りに行く言語1
   priority[1] 取りに行く言語2

   priority[2] 落とさない言語1
   priority[3] 落とさない言語2 できれば取りにいく
   priority[4] 落とさない言語3

   priority[5] 捨てる言語
 */

// ターンでの変数
int turn; // 現在のターン
bool isweekday; // 平日か？
int B[N][P]; // B[n][p] = プレイヤーpの言語nへの信者数
int R[N]; // 自分の本当の投票数
int W[N]; // 前の休日までの、明らかになっていない休日の布教回数(自分を除く)
int days; // 最大数
int L[wdays]; // 出力

void first_init() {
  // 初期化・入力
  int x;
  cin >> x;
  cin >> x;
  cin >> x;
  for (int i=0; i<N; i++) {
    cin >> A[i];
  }
  fill(W, W+N, 0);
  // priorityの確定
  bool used[N];
  fill(used, used+N, false);
  // priority[2]の確定
  for (int i=maxpt; i>=minpt; i--) {
    for (int j=0; j<N; j++) {
      if (A[j] == i) {
	priority[2] = j;
	used[j] = true;
	goto EXIT_OF_PRIORITY_2;
      }
    }
  }
 EXIT_OF_PRIORITY_2:
  // priority[0][1]の確定
  int count = 0;
  for (int i=maxpt; i>=minpt; i--) {
    for (int j=N-1; j>=0; j--) {
      if (!used[j] && A[j] == i) {
	priority[count++] = j;
	used[j] = true;
	if (count == 2) {
	  goto EXIT_OF_PRIORITY_01;
	}
      }
    }
  }
 EXIT_OF_PRIORITY_01:
  // priority[3][4][5]の確定
  count = 3;
  for (int i=maxpt; i>=minpt; i--) {
    for (int j=N-1; j>=0; j--) {
      if (!used[j] && A[j] == i) {
	priority[count++] = j;
	used[j] = true;
	if (count == 5) {
	  goto EXIT_OF_PRIORITY_345;
	}
      }
    }
  }
 EXIT_OF_PRIORITY_345:
  return;
}

void turn_init() {
  cin >> turn;
  char D;
  cin >> D;
  isweekday = (D == 'W');
  if (isweekday) {
    days = wdays;
  } else {
    days = hdays;
  }
  for (int i=0; i<N; i++) {
    for (int j=0; j<P; j++) {
      cin >> B[i][j];
    }
  }
  for (int i=0; i<N; i++) {
    cin >> R[i];
  }
  if (turn == 6) {
    fill(W, W+P, 0);
  }
  if (isweekday) {
    for (int i=0; i<N; i++) {
      int w;
      cin >> w;
      W[i] += w;
    }
  }
}

bool hantei(int lang, bool istop) {
  // // cerr << "days = " << days << endl;
  int m = B[lang][1];
  for (int i=1; i<P; i++) {
    if (istop) {
      m = max(m, B[lang][i]);
    } else {
      m = min(m, B[lang][i]);
    }
  }
  return (R[lang] >= m + W[lang]);
}

bool isgood(int lang_priority) {
  int lang = priority[lang_priority];
  if (lang_priority <= 1) {
    return hantei(lang, true);
  } else {
    return hantei(lang, false);
  }
}

void determine_L() {
  if (turn == 1) {
    for (int i=0; i<days; i++) {
      L[i] = priority[4-i];
    }
  } else if (turn == 2) {
    for (int i=0; i<days; i++) {
      L[i] = priority[0];
    }
  } else {
    int now_c = 0;
    int now_p = 0;
    // 戦略に基づき割り振る
    while (now_p < 5 && now_c < days) {
      if (!isgood(now_p)) {
	int lang = priority[now_p];
	L[now_c++] = lang;
	R[lang] += ((isweekday) ? 1 : 2);
      } else {
	now_p++;
      }
    }
    // 枠が余ったら
    while (now_c < days) {
      L[now_c++] = priority[3];
    }
  }
}

void turn_output() {
  determine_L();
  for (int i=0; i<days; i++) {
    cout << L[i];
    if (i != days-1) {
      cout << " ";
    }
    if(!isweekday) {
      W[L[i]]--;
    }
  }
  cout << endl;
}

int main() {
  cout << "READY" << endl;
  // ゲーム設定の入力
  first_init();
  // ターン情報の入力
  for (int t=1; t<=T; t++) {
    turn_init();
    turn_output();
  }
}
<commit_msg>Kを追加。係数がポイントだと気づいたので。<commit_after>#include <iostream>
#include <algorithm>
#include <cassert>
using namespace std;

// 大域変数
const int T = 9; // 全ターン数
const int P = 4; // プレイヤー数
const int N = 6; // プログラミングの言語数
const int maxpt = 6;
const int minpt = 3;
const int wdays = 5;
const int hdays = 2;
int A[N]; // 言語の注目数
int priority[N];
/*
   priority[0] 取りに行く言語1
   priority[1] 取りに行く言語2

   priority[2] 落とさない言語1
   priority[3] 落とさない言語2 できれば取りにいく
   priority[4] 落とさない言語3

   priority[5] 捨てる言語
 */

double K = 1.3;

// ターンでの変数
int turn; // 現在のターン
bool isweekday; // 平日か？
int B[N][P]; // B[n][p] = プレイヤーpの言語nへの信者数
int R[N]; // 自分の本当の投票数
int W[N]; // 前の休日までの、明らかになっていない休日の布教回数(自分を除く)
int days; // 最大数
int L[wdays]; // 出力

void first_init() {
  // 初期化・入力
  int x;
  cin >> x;
  cin >> x;
  cin >> x;
  for (int i=0; i<N; i++) {
    cin >> A[i];
  }
  fill(W, W+N, 0);
  // priorityの確定
  bool used[N];
  fill(used, used+N, false);
  // priority[2]の確定
  for (int i=maxpt; i>=minpt; i--) {
    for (int j=0; j<N; j++) {
      if (A[j] == i) {
	priority[2] = j;
	used[j] = true;
	goto EXIT_OF_PRIORITY_2;
      }
    }
  }
 EXIT_OF_PRIORITY_2:
  // priority[0][1]の確定
  int count = 0;
  for (int i=maxpt; i>=minpt; i--) {
    for (int j=N-1; j>=0; j--) {
      if (!used[j] && A[j] == i) {
	priority[count++] = j;
	used[j] = true;
	if (count == 2) {
	  goto EXIT_OF_PRIORITY_01;
	}
      }
    }
  }
 EXIT_OF_PRIORITY_01:
  // priority[3][4][5]の確定
  count = 3;
  for (int i=maxpt; i>=minpt; i--) {
    for (int j=N-1; j>=0; j--) {
      if (!used[j] && A[j] == i) {
	priority[count++] = j;
	used[j] = true;
	if (count == 5) {
	  goto EXIT_OF_PRIORITY_345;
	}
      }
    }
  }
 EXIT_OF_PRIORITY_345:
  return;
}

void turn_init() {
  cin >> turn;
  char D;
  cin >> D;
  isweekday = (D == 'W');
  if (isweekday) {
    days = wdays;
  } else {
    days = hdays;
  }
  for (int i=0; i<N; i++) {
    for (int j=0; j<P; j++) {
      cin >> B[i][j];
    }
  }
  for (int i=0; i<N; i++) {
    cin >> R[i];
  }
  if (turn == 6) {
    fill(W, W+P, 0);
  }
  if (isweekday) {
    for (int i=0; i<N; i++) {
      int w;
      cin >> w;
      W[i] += w;
    }
  }
}

bool hantei(int lang, bool istop) {
  // // cerr << "days = " << days << endl;
  int m = B[lang][1];
  for (int i=1; i<P; i++) {
    if (istop) {
      m = max(m, B[lang][i]);
    } else {
      m = min(m, B[lang][i]);
    }
  }
  return (R[lang] >= m + K*W[lang]);
}

bool isgood(int lang_priority) {
  int lang = priority[lang_priority];
  if (lang_priority <= 1) {
    return hantei(lang, true);
  } else {
    return hantei(lang, false);
  }
}

void determine_L() {
  if (turn == 1) {
    for (int i=0; i<days; i++) {
      L[i] = priority[4-i];
    }
  } else if (turn == 2) {
    for (int i=0; i<days; i++) {
      L[i] = priority[0];
    }
  } else {
    int now_c = 0;
    int now_p = 0;
    // 戦略に基づき割り振る
    while (now_p < 5 && now_c < days) {
      if (!isgood(now_p)) {
	int lang = priority[now_p];
	L[now_c++] = lang;
	R[lang] += ((isweekday) ? 1 : 2);
      } else {
	now_p++;
      }
    }
    // 枠が余ったら
    while (now_c < days) {
      L[now_c++] = priority[3];
    }
  }
}

void turn_output() {
  determine_L();
  for (int i=0; i<days; i++) {
    cout << L[i];
    if (i != days-1) {
      cout << " ";
    }
    if(!isweekday) {
      W[L[i]]--;
    }
  }
  cout << endl;
}

int main() {
  cout << "READY" << endl;
  // ゲーム設定の入力
  first_init();
  // ターン情報の入力
  for (int t=1; t<=T; t++) {
    turn_init();
    turn_output();
  }
}
<|endoftext|>


<commit_before>// Copyright (c) 2013, German Neuroinformatics Node (G-Node)
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted under the terms of the BSD License. See
// LICENSE file in the root of the Project.

#include <nix/hdf5/RepresentationHDF5.hpp>

using namespace std;

namespace nix {
namespace hdf5 {

string linkTypeToString(LinkType link_type) {
    static vector<string> type_names = {"tagged", "untagged", "indexed"};
    return type_names[static_cast<int>(link_type)];
}

LinkType linkTypeFromString(const string &str) {
    if (str == "tagged")
        return LinkType::Tagged;
    else if (str == "untagged")
        return LinkType::Untagged;
    else if (str == "indexed")
        return LinkType::Indexed;
    else
        throw runtime_error("Unable to create a LinkType from the string: " + str);
}

RepresentationHDF5::RepresentationHDF5(const RepresentationHDF5 &representation)
    : EntityHDF5(representation.file(), representation.group(), representation.id()),
      block(representation.block)
{}

RepresentationHDF5::RepresentationHDF5(const File &file, const Block &block, const Group &group,
                                       const string &id)
    : EntityHDF5(file, group, id), block(block)
{}

RepresentationHDF5::RepresentationHDF5(const File &file, const Block &block, const Group &group,
                                       const string &id, time_t time)
    : EntityHDF5(file, group, id, time), block(block)
{}

void RepresentationHDF5::linkType(LinkType link_type) {
    group().setAttr("link_type", linkTypeToString(link_type));
    forceUpdatedAt();
}

void RepresentationHDF5::data(const std::string &data_array_id){
    group().setAttr("data", data_array_id);
    forceUpdatedAt();
}

DataArray RepresentationHDF5::data() const{
    string dataId;
    group().getAttr("data", dataId);
    return block.getDataArray(dataId);
}

LinkType RepresentationHDF5::linkType() const {
    string link_type;
    group().getAttr("link_type", link_type);
    return linkTypeFromString(link_type);
}

RepresentationHDF5::~RepresentationHDF5() {}

} // namespace hdf5
} // namespace nix
<commit_msg>Modified "data" and "linkType" getters in "Representation" to check whether fields exist.<commit_after>// Copyright (c) 2013, German Neuroinformatics Node (G-Node)
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted under the terms of the BSD License. See
// LICENSE file in the root of the Project.

#include <nix/hdf5/RepresentationHDF5.hpp>

using namespace std;

namespace nix {
namespace hdf5 {

string linkTypeToString(LinkType link_type) {
    static vector<string> type_names = {"tagged", "untagged", "indexed"};
    return type_names[static_cast<int>(link_type)];
}

LinkType linkTypeFromString(const string &str) {
    if (str == "tagged")
        return LinkType::Tagged;
    else if (str == "untagged")
        return LinkType::Untagged;
    else if (str == "indexed")
        return LinkType::Indexed;
    else
        throw runtime_error("Unable to create a LinkType from the string: " + str);
}

RepresentationHDF5::RepresentationHDF5(const RepresentationHDF5 &representation)
    : EntityHDF5(representation.file(), representation.group(), representation.id()),
      block(representation.block)
{}

RepresentationHDF5::RepresentationHDF5(const File &file, const Block &block, const Group &group,
                                       const string &id)
    : EntityHDF5(file, group, id), block(block)
{}

RepresentationHDF5::RepresentationHDF5(const File &file, const Block &block, const Group &group,
                                       const string &id, time_t time)
    : EntityHDF5(file, group, id, time), block(block)
{}

void RepresentationHDF5::linkType(LinkType link_type) {
    group().setAttr("link_type", linkTypeToString(link_type));
    forceUpdatedAt();
}

void RepresentationHDF5::data(const std::string &data_array_id){
    group().setAttr("data", data_array_id);
    forceUpdatedAt();
}

DataArray RepresentationHDF5::data() const{
    if(group().hasAttr("data")) {
        string dataId;
        group().getAttr("data", dataId);
        if(block.hasDataArray(dataId)) {
            return block.getDataArray(dataId);
        } else {
            throw std::runtime_error("Data array not found by id in Block");
        }
    } else {
        throw std::runtime_error("data field not set in group");
    }
}

LinkType RepresentationHDF5::linkType() const {
    if(group().hasAttr("link_type")) {
        string link_type;
        group().getAttr("link_type", link_type);
        return linkTypeFromString(link_type);
    } else {
        throw std::runtime_error("link_type field not set in group");
    }
}

RepresentationHDF5::~RepresentationHDF5() {}

} // namespace hdf5
} // namespace nix
<|endoftext|>


<commit_before>/*
 * Copyright © 2010 Intel Corporation
 *
 * 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 (including the next
 * paragraph) 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.
 */

#include <stdlib.h>
#include "glsl_symbol_table.h"
#include "glsl_parser_extras.h"
#include "glsl_types.h"
#include "ir.h"

static void
generate_unop(exec_list *instructions,
	      ir_variable **declarations,
	      const glsl_type *type,
	      enum ir_expression_operation op)
{
   ir_dereference *const retval = new ir_dereference(declarations[16]);
   ir_dereference *const arg = new ir_dereference(declarations[0]);
   ir_rvalue *result;

   result = new ir_expression(op, type, arg, NULL);

   ir_instruction *inst = new ir_assignment(retval, result, NULL);
   instructions->push_tail(inst);
}

static void
generate_binop(exec_list *instructions,
	       ir_variable **declarations,
	       const glsl_type *type,
	       enum ir_expression_operation op)
{
   ir_dereference *const retval = new ir_dereference(declarations[16]);
   ir_dereference *const arg1 = new ir_dereference(declarations[0]);
   ir_dereference *const arg2 = new ir_dereference(declarations[1]);
   ir_rvalue *result;

   result = new ir_expression(op, type, arg1, arg2);

   ir_instruction *inst = new ir_assignment(retval, result, NULL);
   instructions->push_tail(inst);
}

static void
generate_exp(exec_list *instructions,
	     ir_variable **declarations,
	     const glsl_type *type)
{
   generate_unop(instructions, declarations, type, ir_unop_exp);
}

static void
generate_log(exec_list *instructions,
	     ir_variable **declarations,
	     const glsl_type *type)
{
   generate_unop(instructions, declarations, type, ir_unop_log);
}

static void
generate_exp2(exec_list *instructions,
	      ir_variable **declarations,
	      const glsl_type *type)
{
   generate_unop(instructions, declarations, type, ir_unop_exp2);
}

static void
generate_log2(exec_list *instructions,
	      ir_variable **declarations,
	      const glsl_type *type)
{
   generate_unop(instructions, declarations, type, ir_unop_log2);
}

static void
generate_rsq(exec_list *instructions,
	       ir_variable **declarations,
	       const glsl_type *type)
{
   generate_unop(instructions, declarations, type, ir_unop_rsq);
}

static void
generate_sqrt(exec_list *instructions,
	       ir_variable **declarations,
	       const glsl_type *type)
{
   generate_unop(instructions, declarations, type, ir_unop_sqrt);
}

static void
generate_abs(exec_list *instructions,
	     ir_variable **declarations,
	     const glsl_type *type)
{
   generate_unop(instructions, declarations, type, ir_unop_abs);
}

static void
generate_ceil(exec_list *instructions,
	      ir_variable **declarations,
	      const glsl_type *type)
{
   generate_unop(instructions, declarations, type, ir_unop_ceil);
}

static void
generate_floor(exec_list *instructions,
	       ir_variable **declarations,
	       const glsl_type *type)
{
   generate_unop(instructions, declarations, type, ir_unop_floor);
}

static void
generate_mod(exec_list *instructions,
	       ir_variable **declarations,
	       const glsl_type *type)
{
   generate_binop(instructions, declarations, type, ir_binop_mod);
}

static void
generate_min(exec_list *instructions,
	       ir_variable **declarations,
	       const glsl_type *type)
{
   generate_binop(instructions, declarations, type, ir_binop_min);
}

static void
generate_max(exec_list *instructions,
	       ir_variable **declarations,
	       const glsl_type *type)
{
   generate_binop(instructions, declarations, type, ir_binop_max);
}

static void
generate_pow(exec_list *instructions,
	       ir_variable **declarations,
	       const glsl_type *type)
{
   generate_binop(instructions, declarations, type, ir_binop_pow);
}

void
generate_function_instance(ir_function *f,
			   const char *name,
			   exec_list *instructions,
			   int n_args,
			   void (*generate)(exec_list *instructions,
					    ir_variable **declarations,
					    const glsl_type *type),
			   const glsl_type *ret_type,
			   const glsl_type *type)
{
   ir_variable *declarations[17];

   ir_function_signature *const sig = new ir_function_signature(type);
   f->signatures.push_tail(sig);

   ir_label *const label = new ir_label(name);
   instructions->push_tail(label);
   sig->definition = label;
   static const char *arg_names[] = {
      "arg0",
      "arg1"
   };
   int i;

   for (i = 0; i < n_args; i++) {
      ir_variable *var = new ir_variable(type, arg_names[i]);

      var->mode = ir_var_in;
      sig->parameters.push_tail(var);

      var = new ir_variable(type, arg_names[i]);

      declarations[i] = var;
   }

   ir_variable *retval = new ir_variable(ret_type, "__retval");
   instructions->push_tail(retval);

   declarations[16] = retval;

   generate(instructions, declarations, type);
}

void
make_gentype_function(glsl_symbol_table *symtab, exec_list *instructions,
		      const char *name,
		      int n_args,
		      void (*generate)(exec_list *instructions,
				       ir_variable **declarations,
				       const glsl_type *type))
{
   ir_function *const f = new ir_function(name);
   const glsl_type *float_type = glsl_type::float_type;
   const glsl_type *vec2_type = glsl_type::get_instance(GLSL_TYPE_FLOAT, 2, 1);
   const glsl_type *vec3_type = glsl_type::get_instance(GLSL_TYPE_FLOAT, 3, 1);
   const glsl_type *vec4_type = glsl_type::get_instance(GLSL_TYPE_FLOAT, 4, 1);

   bool added = symtab->add_function(name, f);
   assert(added);

   generate_function_instance(f, name, instructions, n_args, generate,
			      float_type, float_type);
   generate_function_instance(f, name, instructions, n_args, generate,
			      vec2_type, vec2_type);
   generate_function_instance(f, name, instructions, n_args, generate,
			      vec3_type, vec3_type);
   generate_function_instance(f, name, instructions, n_args, generate,
			      vec4_type, vec4_type);
}

static void
generate_length(exec_list *instructions,
		ir_variable **declarations,
		const glsl_type *type)
{
   ir_dereference *const retval = new ir_dereference(declarations[16]);
   ir_dereference *const arg = new ir_dereference(declarations[0]);
   ir_rvalue *result, *temp;

   (void)type;

   /* FINISHME: implement the abs(arg) variant for length(float f) */

   temp = new ir_expression(ir_binop_dot, glsl_type::float_type, arg, arg);
   result = new ir_expression(ir_unop_sqrt, glsl_type::float_type, temp, NULL);

   ir_instruction *inst = new ir_assignment(retval, result, NULL);
   instructions->push_tail(inst);
}

void
generate_length_functions(glsl_symbol_table *symtab, exec_list *instructions)
{
   const char *name = "length";
   ir_function *const f = new ir_function(name);
   const glsl_type *float_type = glsl_type::float_type;
   const glsl_type *vec2_type = glsl_type::get_instance(GLSL_TYPE_FLOAT, 2, 1);
   const glsl_type *vec3_type = glsl_type::get_instance(GLSL_TYPE_FLOAT, 3, 1);
   const glsl_type *vec4_type = glsl_type::get_instance(GLSL_TYPE_FLOAT, 4, 1);

   bool added = symtab->add_function(name, f);
   assert(added);

   generate_function_instance(f, name, instructions, 1, generate_length,
			      float_type, float_type);
   generate_function_instance(f, name, instructions, 1, generate_length,
			      float_type, vec2_type);
   generate_function_instance(f, name, instructions, 1, generate_length,
			      float_type, vec3_type);
   generate_function_instance(f, name, instructions, 1, generate_length,
			      float_type, vec4_type);
}

static void
generate_dot(exec_list *instructions,
		ir_variable **declarations,
		const glsl_type *type)
{
   ir_dereference *const retval = new ir_dereference(declarations[16]);
   ir_dereference *const arg = new ir_dereference(declarations[0]);
   ir_rvalue *result;

   (void)type;

   result = new ir_expression(ir_binop_dot, glsl_type::float_type, arg, arg);

   ir_instruction *inst = new ir_assignment(retval, result, NULL);
   instructions->push_tail(inst);
}

void
generate_dot_functions(glsl_symbol_table *symtab, exec_list *instructions)
{
   const char *name = "dot";
   ir_function *const f = new ir_function(name);
   const glsl_type *float_type = glsl_type::float_type;
   const glsl_type *vec2_type = glsl_type::get_instance(GLSL_TYPE_FLOAT, 2, 1);
   const glsl_type *vec3_type = glsl_type::get_instance(GLSL_TYPE_FLOAT, 3, 1);
   const glsl_type *vec4_type = glsl_type::get_instance(GLSL_TYPE_FLOAT, 4, 1);

   bool added = symtab->add_function(name, f);
   assert(added);

   generate_function_instance(f, name, instructions, 1, generate_dot,
			      float_type, float_type);
   generate_function_instance(f, name, instructions, 1, generate_dot,
			      float_type, vec2_type);
   generate_function_instance(f, name, instructions, 1, generate_dot,
			      float_type, vec3_type);
   generate_function_instance(f, name, instructions, 1, generate_dot,
			      float_type, vec4_type);
}

void
generate_110_functions(glsl_symbol_table *symtab, exec_list *instructions)
{
   /* FINISHME: radians() */
   /* FINISHME: degrees() */
   /* FINISHME: sin() */
   /* FINISHME: cos() */
   /* FINISHME: tan() */
   /* FINISHME: asin() */
   /* FINISHME: acos() */
   /* FINISHME: atan(y,x) */
   /* FINISHME: atan(y/x) */
   make_gentype_function(symtab, instructions, "pow", 2, generate_pow);
   make_gentype_function(symtab, instructions, "exp", 1, generate_exp);
   make_gentype_function(symtab, instructions, "log", 1, generate_log);
   make_gentype_function(symtab, instructions, "exp2", 1, generate_exp2);
   make_gentype_function(symtab, instructions, "log2", 1, generate_log2);
   make_gentype_function(symtab, instructions, "sqrt", 1, generate_sqrt);
   make_gentype_function(symtab, instructions, "inversesqrt", 1, generate_rsq);
   make_gentype_function(symtab, instructions, "abs", 1, generate_abs);
   /* FINISHME: sign() */
   make_gentype_function(symtab, instructions, "floor", 1, generate_floor);
   make_gentype_function(symtab, instructions, "ceil", 1, generate_ceil);
   /* FINISHME: fract() */
   /* FINISHME: mod(x, float y) */
   make_gentype_function(symtab, instructions, "mod", 2, generate_mod);
   make_gentype_function(symtab, instructions, "min", 2, generate_min);
   /* FINISHME: min(x, float y) */
   make_gentype_function(symtab, instructions, "max", 2, generate_max);
   /* FINISHME: max(x, float y) */
   /* FINISHME: clamp() */
   /* FINISHME: clamp() */
   /* FINISHME: mix() */
   /* FINISHME: mix() */
   /* FINISHME: step() */
   /* FINISHME: step() */
   /* FINISHME: smoothstep() */
   /* FINISHME: smoothstep() */
   /* FINISHME: floor() */
   /* FINISHME: step() */
   generate_length_functions(symtab, instructions);
   /* FINISHME: distance() */
   generate_dot_functions(symtab, instructions);
   /* FINISHME: cross() */
   /* FINISHME: normalize() */
   /* FINISHME: ftransform() */
   /* FINISHME: faceforward() */
   /* FINISHME: reflect() */
   /* FINISHME: refract() */
   /* FINISHME: matrixCompMult() */
   /* FINISHME: lessThan() */
   /* FINISHME: lessThanEqual() */
   /* FINISHME: greaterThan() */
   /* FINISHME: greaterThanEqual() */
   /* FINISHME: equal() */
   /* FINISHME: notEqual() */
   /* FINISHME: any() */
   /* FINISHME: all() */
   /* FINISHME: not() */
   /* FINISHME: texture*() */
   /* FINISHME: shadow*() */
   /* FINISHME: dFd[xy]() */
   /* FINISHME: fwidth() */
}

void
_mesa_glsl_initialize_functions(exec_list *instructions,
				struct _mesa_glsl_parse_state *state)
{
   generate_110_functions(state->symbols, instructions);
}
<commit_msg>Add the instruction for the parameter variable declarations of builtin funcs.<commit_after>/*
 * Copyright © 2010 Intel Corporation
 *
 * 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 (including the next
 * paragraph) 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.
 */

#include <stdlib.h>
#include "glsl_symbol_table.h"
#include "glsl_parser_extras.h"
#include "glsl_types.h"
#include "ir.h"

static void
generate_unop(exec_list *instructions,
	      ir_variable **declarations,
	      const glsl_type *type,
	      enum ir_expression_operation op)
{
   ir_dereference *const retval = new ir_dereference(declarations[16]);
   ir_dereference *const arg = new ir_dereference(declarations[0]);
   ir_rvalue *result;

   result = new ir_expression(op, type, arg, NULL);

   ir_instruction *inst = new ir_assignment(retval, result, NULL);
   instructions->push_tail(inst);
}

static void
generate_binop(exec_list *instructions,
	       ir_variable **declarations,
	       const glsl_type *type,
	       enum ir_expression_operation op)
{
   ir_dereference *const retval = new ir_dereference(declarations[16]);
   ir_dereference *const arg1 = new ir_dereference(declarations[0]);
   ir_dereference *const arg2 = new ir_dereference(declarations[1]);
   ir_rvalue *result;

   result = new ir_expression(op, type, arg1, arg2);

   ir_instruction *inst = new ir_assignment(retval, result, NULL);
   instructions->push_tail(inst);
}

static void
generate_exp(exec_list *instructions,
	     ir_variable **declarations,
	     const glsl_type *type)
{
   generate_unop(instructions, declarations, type, ir_unop_exp);
}

static void
generate_log(exec_list *instructions,
	     ir_variable **declarations,
	     const glsl_type *type)
{
   generate_unop(instructions, declarations, type, ir_unop_log);
}

static void
generate_exp2(exec_list *instructions,
	      ir_variable **declarations,
	      const glsl_type *type)
{
   generate_unop(instructions, declarations, type, ir_unop_exp2);
}

static void
generate_log2(exec_list *instructions,
	      ir_variable **declarations,
	      const glsl_type *type)
{
   generate_unop(instructions, declarations, type, ir_unop_log2);
}

static void
generate_rsq(exec_list *instructions,
	       ir_variable **declarations,
	       const glsl_type *type)
{
   generate_unop(instructions, declarations, type, ir_unop_rsq);
}

static void
generate_sqrt(exec_list *instructions,
	       ir_variable **declarations,
	       const glsl_type *type)
{
   generate_unop(instructions, declarations, type, ir_unop_sqrt);
}

static void
generate_abs(exec_list *instructions,
	     ir_variable **declarations,
	     const glsl_type *type)
{
   generate_unop(instructions, declarations, type, ir_unop_abs);
}

static void
generate_ceil(exec_list *instructions,
	      ir_variable **declarations,
	      const glsl_type *type)
{
   generate_unop(instructions, declarations, type, ir_unop_ceil);
}

static void
generate_floor(exec_list *instructions,
	       ir_variable **declarations,
	       const glsl_type *type)
{
   generate_unop(instructions, declarations, type, ir_unop_floor);
}

static void
generate_mod(exec_list *instructions,
	       ir_variable **declarations,
	       const glsl_type *type)
{
   generate_binop(instructions, declarations, type, ir_binop_mod);
}

static void
generate_min(exec_list *instructions,
	       ir_variable **declarations,
	       const glsl_type *type)
{
   generate_binop(instructions, declarations, type, ir_binop_min);
}

static void
generate_max(exec_list *instructions,
	       ir_variable **declarations,
	       const glsl_type *type)
{
   generate_binop(instructions, declarations, type, ir_binop_max);
}

static void
generate_pow(exec_list *instructions,
	       ir_variable **declarations,
	       const glsl_type *type)
{
   generate_binop(instructions, declarations, type, ir_binop_pow);
}

void
generate_function_instance(ir_function *f,
			   const char *name,
			   exec_list *instructions,
			   int n_args,
			   void (*generate)(exec_list *instructions,
					    ir_variable **declarations,
					    const glsl_type *type),
			   const glsl_type *ret_type,
			   const glsl_type *type)
{
   ir_variable *declarations[17];

   ir_function_signature *const sig = new ir_function_signature(type);
   f->signatures.push_tail(sig);

   ir_label *const label = new ir_label(name);
   instructions->push_tail(label);
   sig->definition = label;
   static const char *arg_names[] = {
      "arg0",
      "arg1"
   };
   int i;

   for (i = 0; i < n_args; i++) {
      ir_variable *var = new ir_variable(type, arg_names[i]);

      var = new ir_variable(type, arg_names[i]);
      var->mode = ir_var_in;
      sig->parameters.push_tail(var);

      var = new ir_variable(type, arg_names[i]);
      var->mode = ir_var_in;
      instructions->push_tail(var);
      declarations[i] = var;
   }

   ir_variable *retval = new ir_variable(ret_type, "__retval");
   instructions->push_tail(retval);

   declarations[16] = retval;

   generate(instructions, declarations, type);
}

void
make_gentype_function(glsl_symbol_table *symtab, exec_list *instructions,
		      const char *name,
		      int n_args,
		      void (*generate)(exec_list *instructions,
				       ir_variable **declarations,
				       const glsl_type *type))
{
   ir_function *const f = new ir_function(name);
   const glsl_type *float_type = glsl_type::float_type;
   const glsl_type *vec2_type = glsl_type::get_instance(GLSL_TYPE_FLOAT, 2, 1);
   const glsl_type *vec3_type = glsl_type::get_instance(GLSL_TYPE_FLOAT, 3, 1);
   const glsl_type *vec4_type = glsl_type::get_instance(GLSL_TYPE_FLOAT, 4, 1);

   bool added = symtab->add_function(name, f);
   assert(added);

   generate_function_instance(f, name, instructions, n_args, generate,
			      float_type, float_type);
   generate_function_instance(f, name, instructions, n_args, generate,
			      vec2_type, vec2_type);
   generate_function_instance(f, name, instructions, n_args, generate,
			      vec3_type, vec3_type);
   generate_function_instance(f, name, instructions, n_args, generate,
			      vec4_type, vec4_type);
}

static void
generate_length(exec_list *instructions,
		ir_variable **declarations,
		const glsl_type *type)
{
   ir_dereference *const retval = new ir_dereference(declarations[16]);
   ir_dereference *const arg = new ir_dereference(declarations[0]);
   ir_rvalue *result, *temp;

   (void)type;

   /* FINISHME: implement the abs(arg) variant for length(float f) */

   temp = new ir_expression(ir_binop_dot, glsl_type::float_type, arg, arg);
   result = new ir_expression(ir_unop_sqrt, glsl_type::float_type, temp, NULL);

   ir_instruction *inst = new ir_assignment(retval, result, NULL);
   instructions->push_tail(inst);
}

void
generate_length_functions(glsl_symbol_table *symtab, exec_list *instructions)
{
   const char *name = "length";
   ir_function *const f = new ir_function(name);
   const glsl_type *float_type = glsl_type::float_type;
   const glsl_type *vec2_type = glsl_type::get_instance(GLSL_TYPE_FLOAT, 2, 1);
   const glsl_type *vec3_type = glsl_type::get_instance(GLSL_TYPE_FLOAT, 3, 1);
   const glsl_type *vec4_type = glsl_type::get_instance(GLSL_TYPE_FLOAT, 4, 1);

   bool added = symtab->add_function(name, f);
   assert(added);

   generate_function_instance(f, name, instructions, 1, generate_length,
			      float_type, float_type);
   generate_function_instance(f, name, instructions, 1, generate_length,
			      float_type, vec2_type);
   generate_function_instance(f, name, instructions, 1, generate_length,
			      float_type, vec3_type);
   generate_function_instance(f, name, instructions, 1, generate_length,
			      float_type, vec4_type);
}

static void
generate_dot(exec_list *instructions,
		ir_variable **declarations,
		const glsl_type *type)
{
   ir_dereference *const retval = new ir_dereference(declarations[16]);
   ir_dereference *const arg = new ir_dereference(declarations[0]);
   ir_rvalue *result;

   (void)type;

   result = new ir_expression(ir_binop_dot, glsl_type::float_type, arg, arg);

   ir_instruction *inst = new ir_assignment(retval, result, NULL);
   instructions->push_tail(inst);
}

void
generate_dot_functions(glsl_symbol_table *symtab, exec_list *instructions)
{
   const char *name = "dot";
   ir_function *const f = new ir_function(name);
   const glsl_type *float_type = glsl_type::float_type;
   const glsl_type *vec2_type = glsl_type::get_instance(GLSL_TYPE_FLOAT, 2, 1);
   const glsl_type *vec3_type = glsl_type::get_instance(GLSL_TYPE_FLOAT, 3, 1);
   const glsl_type *vec4_type = glsl_type::get_instance(GLSL_TYPE_FLOAT, 4, 1);

   bool added = symtab->add_function(name, f);
   assert(added);

   generate_function_instance(f, name, instructions, 1, generate_dot,
			      float_type, float_type);
   generate_function_instance(f, name, instructions, 1, generate_dot,
			      float_type, vec2_type);
   generate_function_instance(f, name, instructions, 1, generate_dot,
			      float_type, vec3_type);
   generate_function_instance(f, name, instructions, 1, generate_dot,
			      float_type, vec4_type);
}

void
generate_110_functions(glsl_symbol_table *symtab, exec_list *instructions)
{
   /* FINISHME: radians() */
   /* FINISHME: degrees() */
   /* FINISHME: sin() */
   /* FINISHME: cos() */
   /* FINISHME: tan() */
   /* FINISHME: asin() */
   /* FINISHME: acos() */
   /* FINISHME: atan(y,x) */
   /* FINISHME: atan(y/x) */
   make_gentype_function(symtab, instructions, "pow", 2, generate_pow);
   make_gentype_function(symtab, instructions, "exp", 1, generate_exp);
   make_gentype_function(symtab, instructions, "log", 1, generate_log);
   make_gentype_function(symtab, instructions, "exp2", 1, generate_exp2);
   make_gentype_function(symtab, instructions, "log2", 1, generate_log2);
   make_gentype_function(symtab, instructions, "sqrt", 1, generate_sqrt);
   make_gentype_function(symtab, instructions, "inversesqrt", 1, generate_rsq);
   make_gentype_function(symtab, instructions, "abs", 1, generate_abs);
   /* FINISHME: sign() */
   make_gentype_function(symtab, instructions, "floor", 1, generate_floor);
   make_gentype_function(symtab, instructions, "ceil", 1, generate_ceil);
   /* FINISHME: fract() */
   /* FINISHME: mod(x, float y) */
   make_gentype_function(symtab, instructions, "mod", 2, generate_mod);
   make_gentype_function(symtab, instructions, "min", 2, generate_min);
   /* FINISHME: min(x, float y) */
   make_gentype_function(symtab, instructions, "max", 2, generate_max);
   /* FINISHME: max(x, float y) */
   /* FINISHME: clamp() */
   /* FINISHME: clamp() */
   /* FINISHME: mix() */
   /* FINISHME: mix() */
   /* FINISHME: step() */
   /* FINISHME: step() */
   /* FINISHME: smoothstep() */
   /* FINISHME: smoothstep() */
   /* FINISHME: floor() */
   /* FINISHME: step() */
   generate_length_functions(symtab, instructions);
   /* FINISHME: distance() */
   generate_dot_functions(symtab, instructions);
   /* FINISHME: cross() */
   /* FINISHME: normalize() */
   /* FINISHME: ftransform() */
   /* FINISHME: faceforward() */
   /* FINISHME: reflect() */
   /* FINISHME: refract() */
   /* FINISHME: matrixCompMult() */
   /* FINISHME: lessThan() */
   /* FINISHME: lessThanEqual() */
   /* FINISHME: greaterThan() */
   /* FINISHME: greaterThanEqual() */
   /* FINISHME: equal() */
   /* FINISHME: notEqual() */
   /* FINISHME: any() */
   /* FINISHME: all() */
   /* FINISHME: not() */
   /* FINISHME: texture*() */
   /* FINISHME: shadow*() */
   /* FINISHME: dFd[xy]() */
   /* FINISHME: fwidth() */
}

void
_mesa_glsl_initialize_functions(exec_list *instructions,
				struct _mesa_glsl_parse_state *state)
{
   generate_110_functions(state->symbols, instructions);
}
<|endoftext|>


<commit_before><commit_msg>When removing a body from the scene, remove it also from the list of objects in contact<commit_after><|endoftext|>