<commit_before>// Copyright 2018 Global Phasing Ltd.
//
// Selections.

#ifndef GEMMI_SELECT_HPP_
#define GEMMI_SELECT_HPP_

#include <string>
#include <cstdlib>   // for strtol
#include <cctype>    // for isalpha
#include <climits>   // for INT_MIN, INT_MAX
#include "fail.hpp"  // for fail
#include "util.hpp"  // for is_in_list
#include "model.hpp" // for Model, Chain, etc
#include "iterator.hpp" // for FilterProxy

namespace gemmi {

// from http://www.ccp4.ac.uk/html/pdbcur.html
// Specification of the selection sets:
// either
//     /mdl/chn/s1.i1-s2.i2/at[el]:aloc
// or
//     /mdl/chn/*(res).ic/at[el]:aloc
//

struct Selection {
  struct List {
    bool all = true;
    bool inverted = false;
    std::string list;  // comma-separated

    std::string str() const {
      if (all)
        return "*";
      return inverted ? "!" + list : list;
    }

    // assumes that list.all is checked before this function is called
    bool has(const std::string& name) const {
      if (all)
        return true;
      bool found = is_in_list(name, list);
      return inverted ? !found : found;
    }
  };

  struct FlagList {
    std::string pattern;
    bool has(char flag) const {
      if (pattern.empty())
        return true;
      bool invert = (pattern[0] == '!');
      bool found = (pattern.find(flag, invert ? 1 : 0) != std::string::npos);
      return invert ? !found : found;
    }
  };

  struct SequenceId {
    int seqnum;
    char icode;

    std::string str() const {
      std::string s;
      if (seqnum != INT_MIN && seqnum != INT_MAX)
        s = std::to_string(seqnum);
      if (icode != '*') {
        s += '.';
        if (icode != ' ')
          s += icode;
      }
      return s;
    }

    int compare(const SeqId& seqid) const {
      if (seqnum != *seqid.num)
        return seqnum < *seqid.num ? -1 : 1;
      if (icode != '*' && icode != seqid.icode)
        return icode < seqid.icode ? -1 : 1;
      return 0;
    }
  };

  int mdl = 0;            // 0 = all
  List chain_ids;
  SequenceId from_seqid = {INT_MIN, '*'};
  SequenceId to_seqid = {INT_MAX, '*'};
  List residue_names;
  List atom_names;
  List elements;
  List altlocs;
  FlagList residue_flags;
  FlagList atom_flags;

  std::string to_cid() const {
    std::string cid(1, '/');
    if (mdl != 0)
      cid += std::to_string(mdl);
    cid += '/';
    cid += chain_ids.str();
    cid += '/';
    cid += from_seqid.str();
    if (!residue_names.all) {
      cid += residue_names.str();
    } else {
      cid += '-';
      cid += to_seqid.str();
    }
    cid += '/';
    cid += atom_names.str();
    if (!elements.all)
      cid += "[" + elements.str() + "]";
    if (!altlocs.all)
      cid += ":" + altlocs.str();
    return cid;
  }

  bool matches(const gemmi::Model& model) const {
    return mdl == 0 || std::to_string(mdl) == model.name;
  }
  bool matches(const gemmi::Chain& chain) const {
    return chain_ids.has(chain.name);
  }
  bool matches(const gemmi::Residue& res) const {
    return residue_names.has(res.name) &&
           from_seqid.compare(res.seqid) <= 0 &&
           to_seqid.compare(res.seqid) >= 0 &&
           residue_flags.has(res.flag);
  }
  bool matches(const gemmi::Atom& a) const {
    return atom_names.has(a.name) &&
           elements.has(a.element.uname()) &&
           altlocs.has(std::string(a.altloc ? 0 : 1, a.altloc)) &&
           atom_flags.has(a.flag);
  }
  bool matches(const gemmi::CRA& cra) const {
    return (cra.chain == nullptr || matches(*cra.chain)) &&
           (cra.residue == nullptr || matches(*cra.residue)) &&
           (cra.atom == nullptr || matches(*cra.atom));
  }

  FilterProxy<Selection, Model> models(Structure& st) const {
    return {*this, st.models};
  }
  FilterProxy<Selection, Chain> chains(Model& model) const {
    return {*this, model.chains};
  }
  FilterProxy<Selection, Residue> residues(Chain& chain) const {
    return {*this, chain.residues};
  }
  FilterProxy<Selection, Atom> atoms(Residue& residue) const {
    return {*this, residue.atoms};
  }

  CRA first_in_model(Model& model) const {
    if (matches(model))
      for (Chain& chain : model.chains) {
        if (matches(chain))
          for (Residue& res : chain.residues) {
            if (matches(res))
              for (Atom& atom : res.atoms) {
                if (matches(atom))
                  return {&chain, &res, &atom};
              }
          }
      }
    return {nullptr, nullptr, nullptr};
  }

  std::pair<Model*, CRA> first(Structure& st) const {
    for (Model& model : st.models) {
      CRA cra = first_in_model(model);
      if (cra.chain)
        return {&model, cra};
    }
    return {nullptr, {nullptr, nullptr, nullptr}};
  }

  template<typename T>
  void add_matching_children(const T& orig, T& target) {
    for (const auto& orig_child : orig.children())
      if (matches(orig_child)) {
        target.children().push_back(orig_child.empty_copy());
        add_matching_children(orig_child, target.children().back());
      }
  }
  void add_matching_children(const Atom&, Atom&) {}

  Selection& set_residue_flags(const std::string& pattern) {
    residue_flags.pattern = pattern;
    return *this;
  }
  Selection& set_atom_flags(const std::string& pattern) {
    atom_flags.pattern = pattern;
    return *this;
  }

  template<typename T>
  T copy_selection(const T& orig) {
    T copied = orig.empty_copy();
    add_matching_children(orig, copied);
    return copied;
  }
};

namespace impl {

int determine_omitted_cid_fields(const std::string& cid) {
  if (cid[0] == '/')
    return 0; // model
  if (std::isdigit(cid[0]) || cid[0] == '.' || cid[0] == '(' || cid[0] == '-')
    return 2; // residue
  size_t sep = cid.find_first_of("/(:[");
  if (sep == std::string::npos || cid[sep] == '/')
    return 1; // chain
  if (cid[sep] == '(')
    return 2; // residue
  return 3;  // atom
}

Selection::List make_cid_list(const std::string& cid, size_t pos, size_t end) {
  Selection::List list;
  list.all = (cid[pos] == '*');
  if (cid[pos] == '!') {
    list.inverted = true;
    ++pos;
  }
  list.list = cid.substr(pos, end - pos);
  return list;
}

Selection::SequenceId parse_cid_seqid(const std::string& cid, size_t& pos,
                                      int default_seqnum) {
  size_t initial_pos = pos;
  int seqnum = default_seqnum;
  char icode = ' ';
  if (cid[pos] == '*') {
    ++pos;
    icode = '*';
  } else if (std::isdigit(cid[pos])) {
    char* endptr;
    seqnum = std::strtol(&cid[pos], &endptr, 10);
    pos = endptr - &cid[0];
  }
  if (cid[pos] == '.')
    ++pos;
  if (initial_pos != pos && (std::isalpha(cid[pos]) || cid[pos] == '*'))
    icode = cid[pos++];
  return {seqnum, icode};
}

} // namespace impl

inline Selection parse_cid(const std::string& cid) {
  Selection sel;
  if (cid.empty() || (cid.size() == 1 && cid[0] == '*'))
    return sel;
  int omit = impl::determine_omitted_cid_fields(cid);
  size_t sep = 0;
  // model
  if (omit == 0) {
    sep = cid.find('/', 1);
    if (sep != 1 && cid[1] != '*') {
      char* endptr;
      sel.mdl = std::strtol(&cid[1], &endptr, 10);
      size_t end_pos = endptr - &cid[0];
      if (end_pos != sep && end_pos != cid.length())
        fail("Expected model number first: " + cid);
    }
  }

  // chain
  if (omit <= 1 && sep != std::string::npos) {
    size_t pos = (sep == 0 ? 0 : sep + 1);
    sep = cid.find('/', pos);
    sel.chain_ids = impl::make_cid_list(cid, pos, sep);
  }

  // residue; MMDB CID syntax: s1.i1-s2.i2 or *(res).ic
  // In gemmi both 14.a and 14a are accepted.
  // *(ALA). and *(ALA) and (ALA). can be used instead of (ALA) for
  // compatibility with MMDB.
  if (omit <= 2 && sep != std::string::npos) {
    size_t pos = (sep == 0 ? 0 : sep + 1);
    if (cid[pos] != '(')
      sel.from_seqid = impl::parse_cid_seqid(cid, pos, INT_MIN);
    if (cid[pos] == '(') {
      ++pos;
      size_t right_br = cid.find(')', pos);
      sel.residue_names = impl::make_cid_list(cid, pos, right_br);
      pos = right_br + 1;
    }
    // allow "(RES)." and "(RES).*" and "(RES)*"
    if (cid[pos] == '.')
      ++pos;
    if (cid[pos] == '*')
      ++pos;
    if (cid[pos] == '-') {
      ++pos;
      sel.to_seqid = impl::parse_cid_seqid(cid, pos, INT_MAX);
    }
    sep = pos;
  }

  // atom;  at[el]:aloc
  if (sep < cid.size()) {
    if (sep != 0 && cid[sep] != '/')
        fail("Invalid selection syntax: " + cid);
    size_t pos = (sep == 0 ? 0 : sep + 1);
    size_t end = cid.find_first_of("[:", pos);
    if (end != pos)
      sel.atom_names = impl::make_cid_list(cid, pos, end);
    if (end != std::string::npos) {
      if (cid[end] == '[') {
        pos = end + 1;
        end = cid.find(']', pos);
        sel.elements = impl::make_cid_list(cid, pos, end);
        sel.elements.list = to_upper(sel.elements.list);
        ++end;
      }
      if (cid[end] == ':')
        sel.altlocs = impl::make_cid_list(cid, end + 1, std::string::npos);
      else if (end < cid.length())
        fail("Invalid selection syntax (after ']'): " + cid);
    }
  }

  return sel;
}

} // namespace gemmi
#endif
<commit_msg>optimization<commit_after>// Copyright 2018 Global Phasing Ltd.
//
// Selections.

#ifndef GEMMI_SELECT_HPP_
#define GEMMI_SELECT_HPP_

#include <string>
#include <cstdlib>   // for strtol
#include <cctype>    // for isalpha
#include <climits>   // for INT_MIN, INT_MAX
#include "fail.hpp"  // for fail
#include "util.hpp"  // for is_in_list
#include "model.hpp" // for Model, Chain, etc
#include "iterator.hpp" // for FilterProxy

namespace gemmi {

// from http://www.ccp4.ac.uk/html/pdbcur.html
// Specification of the selection sets:
// either
//     /mdl/chn/s1.i1-s2.i2/at[el]:aloc
// or
//     /mdl/chn/*(res).ic/at[el]:aloc
//

struct Selection {
  struct List {
    bool all = true;
    bool inverted = false;
    std::string list;  // comma-separated

    std::string str() const {
      if (all)
        return "*";
      return inverted ? "!" + list : list;
    }

    bool has(const std::string& name) const {
      if (all)
        return true;
      bool found = is_in_list(name, list);
      return inverted ? !found : found;
    }
  };

  struct FlagList {
    std::string pattern;
    bool has(char flag) const {
      if (pattern.empty())
        return true;
      bool invert = (pattern[0] == '!');
      bool found = (pattern.find(flag, invert ? 1 : 0) != std::string::npos);
      return invert ? !found : found;
    }
  };

  struct SequenceId {
    int seqnum;
    char icode;

    std::string str() const {
      std::string s;
      if (seqnum != INT_MIN && seqnum != INT_MAX)
        s = std::to_string(seqnum);
      if (icode != '*') {
        s += '.';
        if (icode != ' ')
          s += icode;
      }
      return s;
    }

    int compare(const SeqId& seqid) const {
      if (seqnum != *seqid.num)
        return seqnum < *seqid.num ? -1 : 1;
      if (icode != '*' && icode != seqid.icode)
        return icode < seqid.icode ? -1 : 1;
      return 0;
    }
  };

  int mdl = 0;            // 0 = all
  List chain_ids;
  SequenceId from_seqid = {INT_MIN, '*'};
  SequenceId to_seqid = {INT_MAX, '*'};
  List residue_names;
  List atom_names;
  List elements;
  List altlocs;
  FlagList residue_flags;
  FlagList atom_flags;

  std::string to_cid() const {
    std::string cid(1, '/');
    if (mdl != 0)
      cid += std::to_string(mdl);
    cid += '/';
    cid += chain_ids.str();
    cid += '/';
    cid += from_seqid.str();
    if (!residue_names.all) {
      cid += residue_names.str();
    } else {
      cid += '-';
      cid += to_seqid.str();
    }
    cid += '/';
    cid += atom_names.str();
    if (!elements.all)
      cid += "[" + elements.str() + "]";
    if (!altlocs.all)
      cid += ":" + altlocs.str();
    return cid;
  }

  bool matches(const gemmi::Model& model) const {
    return mdl == 0 || std::to_string(mdl) == model.name;
  }
  bool matches(const gemmi::Chain& chain) const {
    return chain_ids.has(chain.name);
  }
  bool matches(const gemmi::Residue& res) const {
    return residue_names.has(res.name) &&
           from_seqid.compare(res.seqid) <= 0 &&
           to_seqid.compare(res.seqid) >= 0 &&
           residue_flags.has(res.flag);
  }
  bool matches(const gemmi::Atom& a) const {
    return atom_names.has(a.name) &&
           (elements.all || elements.has(a.element.uname())) &&
           (altlocs.all || altlocs.has(std::string(a.altloc ? 1 : 0, a.altloc))) &&
           atom_flags.has(a.flag);
  }
  bool matches(const gemmi::CRA& cra) const {
    return (cra.chain == nullptr || matches(*cra.chain)) &&
           (cra.residue == nullptr || matches(*cra.residue)) &&
           (cra.atom == nullptr || matches(*cra.atom));
  }

  FilterProxy<Selection, Model> models(Structure& st) const {
    return {*this, st.models};
  }
  FilterProxy<Selection, Chain> chains(Model& model) const {
    return {*this, model.chains};
  }
  FilterProxy<Selection, Residue> residues(Chain& chain) const {
    return {*this, chain.residues};
  }
  FilterProxy<Selection, Atom> atoms(Residue& residue) const {
    return {*this, residue.atoms};
  }

  CRA first_in_model(Model& model) const {
    if (matches(model))
      for (Chain& chain : model.chains) {
        if (matches(chain))
          for (Residue& res : chain.residues) {
            if (matches(res))
              for (Atom& atom : res.atoms) {
                if (matches(atom))
                  return {&chain, &res, &atom};
              }
          }
      }
    return {nullptr, nullptr, nullptr};
  }

  std::pair<Model*, CRA> first(Structure& st) const {
    for (Model& model : st.models) {
      CRA cra = first_in_model(model);
      if (cra.chain)
        return {&model, cra};
    }
    return {nullptr, {nullptr, nullptr, nullptr}};
  }

  template<typename T>
  void add_matching_children(const T& orig, T& target) {
    for (const auto& orig_child : orig.children())
      if (matches(orig_child)) {
        target.children().push_back(orig_child.empty_copy());
        add_matching_children(orig_child, target.children().back());
      }
  }
  void add_matching_children(const Atom&, Atom&) {}

  Selection& set_residue_flags(const std::string& pattern) {
    residue_flags.pattern = pattern;
    return *this;
  }
  Selection& set_atom_flags(const std::string& pattern) {
    atom_flags.pattern = pattern;
    return *this;
  }

  template<typename T>
  T copy_selection(const T& orig) {
    T copied = orig.empty_copy();
    add_matching_children(orig, copied);
    return copied;
  }
};

namespace impl {

int determine_omitted_cid_fields(const std::string& cid) {
  if (cid[0] == '/')
    return 0; // model
  if (std::isdigit(cid[0]) || cid[0] == '.' || cid[0] == '(' || cid[0] == '-')
    return 2; // residue
  size_t sep = cid.find_first_of("/(:[");
  if (sep == std::string::npos || cid[sep] == '/')
    return 1; // chain
  if (cid[sep] == '(')
    return 2; // residue
  return 3;  // atom
}

Selection::List make_cid_list(const std::string& cid, size_t pos, size_t end) {
  Selection::List list;
  list.all = (cid[pos] == '*');
  if (cid[pos] == '!') {
    list.inverted = true;
    ++pos;
  }
  list.list = cid.substr(pos, end - pos);
  return list;
}

Selection::SequenceId parse_cid_seqid(const std::string& cid, size_t& pos,
                                      int default_seqnum) {
  size_t initial_pos = pos;
  int seqnum = default_seqnum;
  char icode = ' ';
  if (cid[pos] == '*') {
    ++pos;
    icode = '*';
  } else if (std::isdigit(cid[pos])) {
    char* endptr;
    seqnum = std::strtol(&cid[pos], &endptr, 10);
    pos = endptr - &cid[0];
  }
  if (cid[pos] == '.')
    ++pos;
  if (initial_pos != pos && (std::isalpha(cid[pos]) || cid[pos] == '*'))
    icode = cid[pos++];
  return {seqnum, icode};
}

} // namespace impl

inline Selection parse_cid(const std::string& cid) {
  Selection sel;
  if (cid.empty() || (cid.size() == 1 && cid[0] == '*'))
    return sel;
  int omit = impl::determine_omitted_cid_fields(cid);
  size_t sep = 0;
  // model
  if (omit == 0) {
    sep = cid.find('/', 1);
    if (sep != 1 && cid[1] != '*') {
      char* endptr;
      sel.mdl = std::strtol(&cid[1], &endptr, 10);
      size_t end_pos = endptr - &cid[0];
      if (end_pos != sep && end_pos != cid.length())
        fail("Expected model number first: " + cid);
    }
  }

  // chain
  if (omit <= 1 && sep != std::string::npos) {
    size_t pos = (sep == 0 ? 0 : sep + 1);
    sep = cid.find('/', pos);
    sel.chain_ids = impl::make_cid_list(cid, pos, sep);
  }

  // residue; MMDB CID syntax: s1.i1-s2.i2 or *(res).ic
  // In gemmi both 14.a and 14a are accepted.
  // *(ALA). and *(ALA) and (ALA). can be used instead of (ALA) for
  // compatibility with MMDB.
  if (omit <= 2 && sep != std::string::npos) {
    size_t pos = (sep == 0 ? 0 : sep + 1);
    if (cid[pos] != '(')
      sel.from_seqid = impl::parse_cid_seqid(cid, pos, INT_MIN);
    if (cid[pos] == '(') {
      ++pos;
      size_t right_br = cid.find(')', pos);
      sel.residue_names = impl::make_cid_list(cid, pos, right_br);
      pos = right_br + 1;
    }
    // allow "(RES)." and "(RES).*" and "(RES)*"
    if (cid[pos] == '.')
      ++pos;
    if (cid[pos] == '*')
      ++pos;
    if (cid[pos] == '-') {
      ++pos;
      sel.to_seqid = impl::parse_cid_seqid(cid, pos, INT_MAX);
    }
    sep = pos;
  }

  // atom;  at[el]:aloc
  if (sep < cid.size()) {
    if (sep != 0 && cid[sep] != '/')
        fail("Invalid selection syntax: " + cid);
    size_t pos = (sep == 0 ? 0 : sep + 1);
    size_t end = cid.find_first_of("[:", pos);
    if (end != pos)
      sel.atom_names = impl::make_cid_list(cid, pos, end);
    if (end != std::string::npos) {
      if (cid[end] == '[') {
        pos = end + 1;
        end = cid.find(']', pos);
        sel.elements = impl::make_cid_list(cid, pos, end);
        sel.elements.list = to_upper(sel.elements.list);
        ++end;
      }
      if (cid[end] == ':')
        sel.altlocs = impl::make_cid_list(cid, end + 1, std::string::npos);
      else if (end < cid.length())
        fail("Invalid selection syntax (after ']'): " + cid);
    }
  }

  return sel;
}

} // namespace gemmi
#endif
<|endoftext|>


<commit_before>#ifndef __LLVM_IKOS_HPP_
#define __LLVM_IKOS_HPP_

/*
 * Compute invariants for each basic block using a numerical abstract
 * domain.
 */

#include "llvm/Pass.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/ADT/DenseMap.h"
#include "boost/optional.hpp"
#include "ikos/CfgBuilder.hh"

namespace llvm_ikos
{

  using namespace llvm;
  using namespace cfg_impl;

  enum IkosDomain { INTERVALS, CONGRUENCES, INTERVALS_CONGRUENCES, ZONES, OCTAGONS};

  class LlvmIkos : public llvm::ModulePass
  {
    typedef llvm::DenseMap< const llvm::BasicBlock *, ZLinearConstraintSystem > invariants_map_t;

    invariants_map_t m_inv_map;
    IkosDomain       m_absdom;
    bool             m_runlive;

   public:

    typedef invariants_map_t::iterator       iterator;
    typedef invariants_map_t::const_iterator const_iterator;

    static char ID;

    LlvmIkos (IkosDomain absdom = INTERVALS, bool runLive = false);

    ~LlvmIkos (){ m_inv_map.clear(); }

    virtual void getAnalysisUsage (llvm::AnalysisUsage &AU) const
    {
      AU.setPreservesCFG();
    }

    virtual bool runOnModule (llvm::Module& M);

    virtual bool runOnFunction (llvm::Function &F);

    iterator       begin ()       { return m_inv_map.begin(); }
    iterator       end ()         { return m_inv_map.end();   }
    const_iterator begin () const { return m_inv_map.begin(); }
    const_iterator end ()   const { return m_inv_map.end();   }

    ZLinearConstraintSystem operator[] (const llvm::BasicBlock *BB) const
    {
      const_iterator it = m_inv_map.find (BB);
      if (it == m_inv_map.end())
      {
        ZLinearConstraintSystem tt;
        tt += mkTRUE ();
        return tt;
      }
      else return it->second;
    }

    void dump (llvm::Module &M) const;

   private:

    ZLinearConstraint mkTRUE() const
    {
      return ZLinearConstraint ( ZLinearExpression (1) == ZLinearExpression (1));
    }

    ZLinearConstraint mkFALSE() const
    {
      return ZLinearConstraint ( ZLinearExpression (1) == ZLinearExpression (0));
    }

    template<typename AbsDomain>
    bool runOnCfg (cfg_t& cfg, llvm::Function &F, VariableFactory &vfac);

  };

  ModulePass * createLlvmIkosPass (IkosDomain absdomain, bool runLive);

} // end namespace llvm_ikos

#endif
<commit_msg>[FIX] LlvmIkos preserves all passes. Not just CFG.<commit_after>#ifndef __LLVM_IKOS_HPP_
#define __LLVM_IKOS_HPP_

/*
 * Compute invariants for each basic block using a numerical abstract
 * domain.
 */

#include "llvm/Pass.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/ADT/DenseMap.h"
#include "boost/optional.hpp"
#include "ikos/CfgBuilder.hh"

namespace llvm_ikos
{

  using namespace llvm;
  using namespace cfg_impl;

  enum IkosDomain { INTERVALS, CONGRUENCES, INTERVALS_CONGRUENCES, ZONES, OCTAGONS};

  class LlvmIkos : public llvm::ModulePass
  {
    typedef llvm::DenseMap< const llvm::BasicBlock *, ZLinearConstraintSystem > invariants_map_t;

    invariants_map_t m_inv_map;
    IkosDomain       m_absdom;
    bool             m_runlive;

   public:

    typedef invariants_map_t::iterator       iterator;
    typedef invariants_map_t::const_iterator const_iterator;

    static char ID;

    LlvmIkos (IkosDomain absdom = INTERVALS, bool runLive = false);

    ~LlvmIkos (){ m_inv_map.clear(); }

    virtual void getAnalysisUsage (llvm::AnalysisUsage &AU) const
    {AU.setPreservesAll ();}

    virtual bool runOnModule (llvm::Module& M);

    virtual bool runOnFunction (llvm::Function &F);

    iterator       begin ()       { return m_inv_map.begin(); }
    iterator       end ()         { return m_inv_map.end();   }
    const_iterator begin () const { return m_inv_map.begin(); }
    const_iterator end ()   const { return m_inv_map.end();   }

    ZLinearConstraintSystem operator[] (const llvm::BasicBlock *BB) const
    {
      const_iterator it = m_inv_map.find (BB);
      if (it == m_inv_map.end())
      {
        ZLinearConstraintSystem tt;
        tt += mkTRUE ();
        return tt;
      }
      else return it->second;
    }

    void dump (llvm::Module &M) const;

   private:

    ZLinearConstraint mkTRUE() const
    {
      return ZLinearConstraint ( ZLinearExpression (1) == ZLinearExpression (1));
    }

    ZLinearConstraint mkFALSE() const
    {
      return ZLinearConstraint ( ZLinearExpression (1) == ZLinearExpression (0));
    }

    template<typename AbsDomain>
    bool runOnCfg (cfg_t& cfg, llvm::Function &F, VariableFactory &vfac);

  };

  ModulePass * createLlvmIkosPass (IkosDomain absdomain, bool runLive);

} // end namespace llvm_ikos

#endif
<|endoftext|>


<commit_before>//-----------------------------------------------------------------------------
// Jikken - 3D Abstract High Performance Graphics API
// Copyright(c) 2017 Jeff Hutchinson
// Copyright(c) 2017 Tim Barnes
//
// 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.
//-----------------------------------------------------------------------------

#ifndef _JIKKEN_ENUMS_HPP_
#define _JIKKEN_ENUMS_HPP_

#include <cstdint>

namespace Jikken
{
	enum class API : uint8_t
	{
		eNull,
		eOpenGL,
		eVulkan
	};

	enum class BlendState : uint8_t
	{
		eSrcAlpha = 0,
		eOneMinusSrcAlpha
	};

	enum class DepthFunc : uint8_t
	{
		eNever = 0,
		eAlways,
		eLess,
		eEqual,
		eNotEqual,
		eGreater,
		eLessEqual,
		eGreaterEqual
	};

	enum class CullFaceState : uint8_t
	{
		eFront = 0,
		eBack
	};

	enum class WindingOrderState : uint8_t
	{
		eCW = 0,
		eCCW
	};

	enum class PrimitiveType : uint8_t
	{
		eTriangles = 0,
		eTriangleStrip,
		eLines,
		eLineStrip
	};

	enum class ShaderStage : uint8_t
	{
		eVertex = 0,
		eFragment,
		eGeometry,
		eCompute
	};

	enum ClearBufferFlags : uint32_t
	{
		eColor = 1,
		eDepth = 2,
		eStencil = 4
	};

	enum class BufferType : uint8_t
	{
		eVertexBuffer = 0,
		eIndexBuffer,
		eConstantBuffer
	};

	enum class BufferUsageHint : uint8_t
	{
		eStaticDraw = 0,
		eDynamicDraw,
		eStreamDraw
	};

	enum VertexAttributeName : int32_t
	{
		ePOSITION = 0
	};

	enum VertexAttributeType : int32_t
	{
		eFLOAT = 0
	};
}

#endif<commit_msg>BlendState enum update<commit_after>//-----------------------------------------------------------------------------
// Jikken - 3D Abstract High Performance Graphics API
// Copyright(c) 2017 Jeff Hutchinson
// Copyright(c) 2017 Tim Barnes
//
// 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.
//-----------------------------------------------------------------------------

#ifndef _JIKKEN_ENUMS_HPP_
#define _JIKKEN_ENUMS_HPP_

#include <cstdint>

namespace Jikken
{
	enum class API : uint8_t
	{
		eNull,
		eOpenGL,
		eVulkan
	};

	enum class BlendState : uint8_t
	{
		eZero = 0,
		eOne,
		eSrcColor,
		eOneMinusSrcColor,
		eSrcAlpha,
		eOneMinusSrcAlpha,
		eDstAlpha,
		eOneMinusDstAlpha,
		eDstColor,
		eOneMinusDstColor
	};

	enum class DepthFunc : uint8_t
	{
		eNever = 0,
		eAlways,
		eLess,
		eEqual,
		eNotEqual,
		eGreater,
		eLessEqual,
		eGreaterEqual
	};

	enum class CullFaceState : uint8_t
	{
		eFront = 0,
		eBack
	};

	enum class WindingOrderState : uint8_t
	{
		eCW = 0,
		eCCW
	};

	enum class PrimitiveType : uint8_t
	{
		eTriangles = 0,
		eTriangleStrip,
		eLines,
		eLineStrip
	};

	enum class ShaderStage : uint8_t
	{
		eVertex = 0,
		eFragment,
		eGeometry,
		eCompute
	};

	enum ClearBufferFlags : uint32_t
	{
		eColor = 1,
		eDepth = 2,
		eStencil = 4
	};

	enum class BufferType : uint8_t
	{
		eVertexBuffer = 0,
		eIndexBuffer,
		eConstantBuffer
	};

	enum class BufferUsageHint : uint8_t
	{
		eStaticDraw = 0,
		eDynamicDraw,
		eStreamDraw
	};

	enum VertexAttributeName : int32_t
	{
		ePOSITION = 0
	};

	enum VertexAttributeType : int32_t
	{
		eFLOAT = 0
	};
}

#endif<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2006 Artem Pavlenko
 *
 * 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; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

//$Id: utils.hpp 39 2005-04-10 20:39:53Z pavlenko $

#ifndef UTILS_HPP
#define UTILS_HPP

#ifdef MAPNIK_THREADSAFE
#include <boost/thread/mutex.hpp>
#endif

// stl
#include <stdexcept>
#include <cstdlib>
#include <limits>
#include <ctime>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <cmath>

namespace mapnik
{
#ifdef MAPNIK_THREADSAFE
using boost::mutex;
#endif

template <typename T>
class CreateUsingNew
{
public:
    static T* create()
    {
        return new T;
    }
    static void destroy(T* obj)
    {
        delete obj;
    }
};

template <typename T>
class CreateStatic
{
private:
    union MaxAlign
    {
        char t_[sizeof(T)];
        short int shortInt_;
        int int_;
        long int longInt_;
        float float_;
        double double_;
        long double longDouble_;
        struct Test;
        int Test::* pMember_;
        int (Test::*pMemberFn_)(int);
    };

public:

    static T* create()
    {
        static MaxAlign staticMemory;
        return new(&staticMemory) T;
    }
#ifdef __SUNPRO_CC
    // Sun C++ Compiler doesn't handle `volatile` keyword same as GCC.
    static void destroy(T* obj)
#else
        static void destroy(volatile T* obj)
#endif
    {
        obj->~T();
    }
};

template <typename T,
          template <typename T> class CreatePolicy=CreateStatic> class singleton
{
#ifdef __SUNPRO_CC
    /* Sun's C++ compiler will issue the following errors if CreatePolicy<T> is used:
       Error: A class template name was expected instead of mapnik::CreatePolicy<mapnik::T>
       Error: A "friend" declaration must specify a class or function.
    */
    friend class CreatePolicy;
#else
    friend class CreatePolicy<T>;
#endif
    static T* pInstance_;
    static bool destroyed_;
    singleton(const singleton &rhs);
    singleton& operator=(const singleton&);
    static void onDeadReference()
    {
        throw std::runtime_error("dead reference!");
    }

    static void DestroySingleton()
    {
        CreatePolicy<T>::destroy(pInstance_);
        pInstance_ = 0;
        destroyed_=true;
#ifdef MAPNIK_DEBUG
        std::clog << " destroyed singleton \n";
#endif
    }

protected:
#ifdef MAPNIK_THREADSAFE
    static mutex mutex_;
#endif
    singleton() {}
public:
    static  T* instance()
    {
        if (!pInstance_)
        {
#ifdef MAPNIK_THREADSAFE
            mutex::scoped_lock lock(mutex_);
#endif
            if (!pInstance_)
            {

                if (destroyed_)
                {
                    onDeadReference();
                }
                else
                {
                    pInstance_=CreatePolicy<T>::create();
                    // register destruction
                    std::atexit(&DestroySingleton);
                }
            }
        }
        return pInstance_;
    }
};
#ifdef MAPNIK_THREADSAFE
template <typename T,
          template <typename T> class CreatePolicy> mutex singleton<T,CreatePolicy>::mutex_;
#endif

template <typename T,
          template <typename T> class CreatePolicy> T* singleton<T,CreatePolicy>::pInstance_=0;
template <typename T,
          template <typename T> class CreatePolicy> bool singleton<T,CreatePolicy>::destroyed_=false;

}

#endif //UTILS_HPP
<commit_msg>+ fixed template parameter shadowing (clang++)<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2006 Artem Pavlenko
 *
 * 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; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

//$Id: utils.hpp 39 2005-04-10 20:39:53Z pavlenko $

#ifndef UTILS_HPP
#define UTILS_HPP

#ifdef MAPNIK_THREADSAFE
#include <boost/thread/mutex.hpp>
#endif

// stl
#include <stdexcept>
#include <cstdlib>
#include <limits>
#include <ctime>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <cmath>

namespace mapnik
{
#ifdef MAPNIK_THREADSAFE
using boost::mutex;
#endif

template <typename T>
class CreateUsingNew
{
public:
    static T* create()
    {
        return new T;
    }
    static void destroy(T* obj)
    {
        delete obj;
    }
};

template <typename T>
class CreateStatic
{
private:
    union MaxAlign
    {
        char t_[sizeof(T)];
        short int shortInt_;
        int int_;
        long int longInt_;
        float float_;
        double double_;
        long double longDouble_;
        struct Test;
        int Test::* pMember_;
        int (Test::*pMemberFn_)(int);
    };

public:

    static T* create()
    {
        static MaxAlign staticMemory;
        return new(&staticMemory) T;
    }
#ifdef __SUNPRO_CC
    // Sun C++ Compiler doesn't handle `volatile` keyword same as GCC.
    static void destroy(T* obj)
#else
        static void destroy(volatile T* obj)
#endif
    {
        obj->~T();
    }
};

template <typename T,
          template <typename U> class CreatePolicy=CreateStatic> class singleton
{
#ifdef __SUNPRO_CC
    /* Sun's C++ compiler will issue the following errors if CreatePolicy<T> is used:
       Error: A class template name was expected instead of mapnik::CreatePolicy<mapnik::T>
       Error: A "friend" declaration must specify a class or function.
    */
    friend class CreatePolicy;
#else
    friend class CreatePolicy<T>;
#endif
    static T* pInstance_;
    static bool destroyed_;
    singleton(const singleton &rhs);
    singleton& operator=(const singleton&);
    static void onDeadReference()
    {
        throw std::runtime_error("dead reference!");
    }

    static void DestroySingleton()
    {
        CreatePolicy<T>::destroy(pInstance_);
        pInstance_ = 0;
        destroyed_=true;
#ifdef MAPNIK_DEBUG
        std::clog << " destroyed singleton \n";
#endif
    }

protected:
#ifdef MAPNIK_THREADSAFE
    static mutex mutex_;
#endif
    singleton() {}
public:
    static  T* instance()
    {
        if (!pInstance_)
        {
#ifdef MAPNIK_THREADSAFE
            mutex::scoped_lock lock(mutex_);
#endif
            if (!pInstance_)
            {

                if (destroyed_)
                {
                    onDeadReference();
                }
                else
                {
                    pInstance_=CreatePolicy<T>::create();
                    // register destruction
                    std::atexit(&DestroySingleton);
                }
            }
        }
        return pInstance_;
    }
};
#ifdef MAPNIK_THREADSAFE
template <typename T,
          template <typename U> class CreatePolicy> mutex singleton<T,CreatePolicy>::mutex_;
#endif

template <typename T,
          template <typename U> class CreatePolicy> T* singleton<T,CreatePolicy>::pInstance_=0;
template <typename T,
          template <typename U> class CreatePolicy> bool singleton<T,CreatePolicy>::destroyed_=false;

}

#endif //UTILS_HPP
<|endoftext|>


<commit_before>/******************************************************************************
* Copyright (c) 2011, Michael P. Gerlek (mpg@flaxen.com)
*
* 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 Hobu, Inc. or Flaxen Geo Consulting 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.
****************************************************************************/

#pragma once

#include <pdal/third/nanoflann.hpp>

#include <pdal/PointBuffer.hpp>

namespace pdal
{

class PDAL_DLL KDIndex
{
public:
    KDIndex(PointBuffer& buf) : m_buf(buf), m_index(0)
        { m_3d = buf.context().hasDim(Dimension::Id::Z); }

    ~KDIndex()
        { delete m_index; }

    size_t kdtree_get_point_count() const
        { return m_buf.size(); }

    double kdtree_get_pt(const size_t idx, int dim) const
    {
        Dimension::Id::Enum id = Dimension::Id::Unknown;
        switch (dim)
        {
        case 0:
            id = Dimension::Id::X;
            break;
        case 1:
            id = Dimension::Id::Y;
            break;
        case 3:
            id = Dimension::Id::Z;
            break;
        }
        return m_buf.getFieldAs<double>(id, idx);
    }

    double kdtree_distance(const double *p1, const size_t idx_p2,
        size_t size) const
    {
        double d0 = m_buf.getFieldAs<double>(Dimension::Id::X, idx_p2) -
            m_buf.getFieldAs<double>(Dimension::Id::X, size - 1);
        double d1 = m_buf.getFieldAs<double>(Dimension::Id::Y, idx_p2) -
            m_buf.getFieldAs<double>(Dimension::Id::Y, size - 1);

        double output(d0 * d0 + d1 * d1);
        if (m_3d)
        {
            double d2 = m_buf.getFieldAs<double>(Dimension::Id::Z, idx_p2) -
                m_buf.getFieldAs<double>(Dimension::Id::Z, size - 1);
            output += d2 * d2;
        }
        return output;
    }

    template <class BBOX> bool kdtree_get_bbox(BBOX &bb) const
    {
        pdal::Bounds<double> bounds = m_buf.calculateBounds();
        if (bounds.empty())
            return false;

        size_t nDims = m_3d ? 3 : 2;
        for (size_t i = 0; i < nDims; ++i)
        {
            bb[i].low = bounds.getMinimum(i);
            bb[i].high = bounds.getMaximum(i);
        }
        return true;
    }

    std::vector<size_t> radius(
            double const& x,
            double const& y,
            double const& z,
            double const& r) const;

    std::vector<size_t> neighbors(
            double const& x,
            double const& y,
            double const& z,
            double distance,
            boost::uint32_t count = 1) const;

    void build(PointContext ctx, bool b3d = true);

private:
    const PointBuffer& m_buf;
    bool m_3d;

    typedef nanoflann::KDTreeSingleIndexAdaptor<
        nanoflann::L2_Adaptor<double, KDIndex>, KDIndex> my_kd_tree_t;
    my_kd_tree_t* m_index;
};

} // namespace pdal

<commit_msg>Fix KD index typo.<commit_after>/******************************************************************************
* Copyright (c) 2011, Michael P. Gerlek (mpg@flaxen.com)
*
* 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 Hobu, Inc. or Flaxen Geo Consulting 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.
****************************************************************************/

#pragma once

#include <pdal/third/nanoflann.hpp>

#include <pdal/PointBuffer.hpp>

namespace pdal
{

class PDAL_DLL KDIndex
{
public:
    KDIndex(PointBuffer& buf) : m_buf(buf), m_index(0)
        { m_3d = buf.context().hasDim(Dimension::Id::Z); }

    ~KDIndex()
        { delete m_index; }

    size_t kdtree_get_point_count() const
        { return m_buf.size(); }

    double kdtree_get_pt(const size_t idx, int dim) const
    {
        Dimension::Id::Enum id = Dimension::Id::Unknown;
        switch (dim)
        {
        case 0:
            id = Dimension::Id::X;
            break;
        case 1:
            id = Dimension::Id::Y;
            break;
        case 2:
            id = Dimension::Id::Z;
            break;
        }
        return m_buf.getFieldAs<double>(id, idx);
    }

    double kdtree_distance(const double *p1, const size_t idx_p2,
        size_t size) const
    {
        double d0 = m_buf.getFieldAs<double>(Dimension::Id::X, idx_p2) -
            m_buf.getFieldAs<double>(Dimension::Id::X, size - 1);
        double d1 = m_buf.getFieldAs<double>(Dimension::Id::Y, idx_p2) -
            m_buf.getFieldAs<double>(Dimension::Id::Y, size - 1);

        double output(d0 * d0 + d1 * d1);
        if (m_3d)
        {
            double d2 = m_buf.getFieldAs<double>(Dimension::Id::Z, idx_p2) -
                m_buf.getFieldAs<double>(Dimension::Id::Z, size - 1);
            output += d2 * d2;
        }
        return output;
    }

    template <class BBOX> bool kdtree_get_bbox(BBOX &bb) const
    {
        pdal::Bounds<double> bounds = m_buf.calculateBounds();
        if (bounds.empty())
            return false;

        size_t nDims = m_3d ? 3 : 2;
        for (size_t i = 0; i < nDims; ++i)
        {
            bb[i].low = bounds.getMinimum(i);
            bb[i].high = bounds.getMaximum(i);
        }
        return true;
    }

    std::vector<size_t> radius(
            double const& x,
            double const& y,
            double const& z,
            double const& r) const;

    std::vector<size_t> neighbors(
            double const& x,
            double const& y,
            double const& z,
            double distance,
            boost::uint32_t count = 1) const;

    void build(PointContext ctx, bool b3d = true);

private:
    const PointBuffer& m_buf;
    bool m_3d;

    typedef nanoflann::KDTreeSingleIndexAdaptor<
        nanoflann::L2_Adaptor<double, KDIndex>, KDIndex> my_kd_tree_t;
    my_kd_tree_t* m_index;
};

} // namespace pdal

<|endoftext|>


<commit_before>
#pragma once

#include <proxc/version.hpp>

////////////////////////////////////////////////////////////////////////////////
// Detect the compiler
////////////////////////////////////////////////////////////////////////////////

#if defined(_MSC_VER) && !defined(__clang__) // MSVC

#   pragma message("Warning: the native Microsoft compiler is not supported due to lack of proper C++14 support.")

#elif defined(__clang__) && defined(_MSC_VER) // Clang-cl (Clang for Windows)

#   define PROXC_CONFIG_CLANG PROXC_CONFIG_VERSION( \
        __clang_major__, __clang_minor__, __clang_patchlevel__)

#   if PROXC_CONFIG_CLANG < PROXC_CONFIG_VERSION(3, 5, 0)
#       warning "Versions of Clang prior to 3.5.0 are not supported for lack of proper C++14 support."
#   endif

#elif defined(__clang__) && defined(__apple_build_version__) // Apple's Clang

#   if __apple_build_version__ >= 6000051
#       define PROXC_CONFIG_CLANG PROXC_CONFIG_VERSION(3, 6, 0)
#   else
#       warning "Versions of Apple's Clang prior to the one shipped with XCode is not supported."
#   endif

#elif defined(__clang__) // Genuine Clang

#   define PROXC_CONFIG_CLANG PROXC_CONFIG_VERSION( \
        __clang_major__, __clang_minor__, __clang_patchlevel__)

#   if PROXC_CONFIG_CLANG < PROXC_CONFIG_VERSION(3, 5, 0)
#       warning "Versions of Clang prior to 3.5.0 are not supported for lack of proper C++14 support."
#   endif

#elif defined(__GNUC__) // GCC

#   define PROXC_CONFIC_GCC PROXC_CONFIG_VERSION(\
        __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)

#   if PROXC_CONFIC_GCC < PROXC_CONFIG_VERSION(5, 0, 0)
#       warning "Versions of GCC prior to 5.0.0 are not supported for lack of proper C++14 support."
#   endif

#else

#   warning "Your compiler was not detected properly and might not work for ProXC."

#endif

////////////////////////////////////////////////////////////////////////////////
// Detect the compiler for general C++14 capabilities
////////////////////////////////////////////////////////////////////////////////

#if (__cplusplus < 201400)
#   if defined(_MSC_VER)
#       pragma message("Warning: Your compiler doesn't provide C++14 or higher capabilities. Try adding the compiler flag 'std=c++14' or '-std=c++1y'.")
#   else
#       warning "Your compiler doesn't provde C++14 or higher capabilities. Try adding the compiler flag 'std=c++14' or 'std=c++1y'"
#   endif
#endif

////////////////////////////////////////////////////////////////////////////////
// Detect the standard library
////////////////////////////////////////////////////////////////////////////////

#include <cstddef>

#if defined(_LIBCPP_VERSION)

#   define PROXC_CONFIG_LIBCPP PROXC_CONFIG_VERSION( \
        ((_LIBCPP_VERSION) / 1000) % 10, 0, (_LIBCPP_VERSION) % 1000)

#   if PROXC_CONFIG_LIBCPP < PROXC_CONFIG_VERSION(1, 0, 101)
#       warning "Versions of libc++ prior to the one shipped with Clang 3.5.0 are not supported for lack of full C++14 support."
#   endif

#elif defined(__GLIBCXX__)

#   if __GLIBCXX__ < 20150422 // --> the libstdc++ shipped with GCC 5.1.0
#       warning "Versions of libstdc++ prior to the one shipped with GCC 5.1.0 are not supported for lack of full C++14 support."
#   endif

#   define PROXC_CONFIG_LIBSTDCXX

#elif defined(_MSC_VER)

#   define PROXC_CONFIG_LIBMSVCCXX

#else

#   warning "Your standard library was not detected properly and might not work for ProXC."

#endif

////////////////////////////////////////////////////////////////////////////////
// Detect 32- or 64-bit architecture
////////////////////////////////////////////////////////////////////////////////

#ifndef PROXC_ARCH

#if defined(__powerpc__) || defined(__ppc__) || defined(__PPC__) /* PowerPC */

#   if defined(__powerpc64__) || defined(__ppc64__) || defined(__PPC64__) || \
       defined(__64BIT__)     || defined(_LP64)     || defined(__LP64__) /* PowerPC 64-bit */

#       define PROXC_ARCH 64

#   else /* PowerPC 32-bit */

#       define PROXC_ARCH 32

#   endif

#elif defined(__x86_64__) || defined(_M_X64) /* x86 64-bit */

#   define PROXC_ARCH 64

#elif defined(__i386) || defined(_M_IX86) /* x86 32-bit */

#   define PROXC_ARCH 32

#elif defined(_WIN32) || defined(_WIN64) /* Windows */

#   if defined(_WIN64) /* Windows 64-bit */

#       define PROXC_ARCH 64

#   else /* Windows 32-bit */

#       define PROXC_ARCH 32

#   endif

#else /* Unknown architecture */

#   define PROXC_ARCH 64
#   warning "Architecture was neither correctly determined nor specified. Defaults to 64-bit. This can be set with -DPROXC_ARCH={32/64}, for 32-bit or 64-bit respectively."

#endif

#else

static_assert(((PROXC_ARCH) == 32) || ((PROXC_ARCH) == 64), "Architecture specified by PROXC_ARCH only supports 32 or 64 value.");

#endif // PROXC_ARCH

////////////////////////////////////////////////////////////////////////////////
// Namespace macros
////////////////////////////////////////////////////////////////////////////////

#define PROXC_NAMESPACE_BEGIN namespace proxc {

#define PROXC_NAMESPACE_END }

<commit_msg>Added configuration for cache alignment and cacheline length.<commit_after>
#pragma once

#include <proxc/version.hpp>

////////////////////////////////////////////////////////////////////////////////
// Detect the compiler
////////////////////////////////////////////////////////////////////////////////

#if defined(_MSC_VER) && !defined(__clang__) // MSVC

#   pragma message("Warning: the native Microsoft compiler is not supported due to lack of proper C++14 support.")

#elif defined(__clang__) && defined(_MSC_VER) // Clang-cl (Clang for Windows)

#   define PROXC_CONFIG_CLANG PROXC_CONFIG_VERSION( \
        __clang_major__, __clang_minor__, __clang_patchlevel__)

#   if PROXC_CONFIG_CLANG < PROXC_CONFIG_VERSION(3, 5, 0)
#       warning "Versions of Clang prior to 3.5.0 are not supported for lack of proper C++14 support."
#   endif

#elif defined(__clang__) && defined(__apple_build_version__) // Apple's Clang

#   if __apple_build_version__ >= 6000051
#       define PROXC_CONFIG_CLANG PROXC_CONFIG_VERSION(3, 6, 0)
#   else
#       warning "Versions of Apple's Clang prior to the one shipped with XCode is not supported."
#   endif

#elif defined(__clang__) // Genuine Clang

#   define PROXC_CONFIG_CLANG PROXC_CONFIG_VERSION( \
        __clang_major__, __clang_minor__, __clang_patchlevel__)

#   if PROXC_CONFIG_CLANG < PROXC_CONFIG_VERSION(3, 5, 0)
#       warning "Versions of Clang prior to 3.5.0 are not supported for lack of proper C++14 support."
#   endif

#elif defined(__GNUC__) // GCC

#   define PROXC_CONFIC_GCC PROXC_CONFIG_VERSION(\
        __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)

#   if PROXC_CONFIC_GCC < PROXC_CONFIG_VERSION(5, 0, 0)
#       warning "Versions of GCC prior to 5.0.0 are not supported for lack of proper C++14 support."
#   endif

#else

#   warning "Your compiler was not detected properly and might not work for ProXC."

#endif

////////////////////////////////////////////////////////////////////////////////
// Detect the compiler for general C++14 capabilities
////////////////////////////////////////////////////////////////////////////////

#if (__cplusplus < 201400)
#   if defined(_MSC_VER)
#       pragma message("Warning: Your compiler doesn't provide C++14 or higher capabilities. Try adding the compiler flag 'std=c++14' or '-std=c++1y'.")
#   else
#       warning "Your compiler doesn't provde C++14 or higher capabilities. Try adding the compiler flag 'std=c++14' or 'std=c++1y'"
#   endif
#endif

////////////////////////////////////////////////////////////////////////////////
// Detect the standard library
////////////////////////////////////////////////////////////////////////////////

#include <cstddef>

#if defined(_LIBCPP_VERSION)

#   define PROXC_CONFIG_LIBCPP PROXC_CONFIG_VERSION( \
        ((_LIBCPP_VERSION) / 1000) % 10, 0, (_LIBCPP_VERSION) % 1000)

#   if PROXC_CONFIG_LIBCPP < PROXC_CONFIG_VERSION(1, 0, 101)
#       warning "Versions of libc++ prior to the one shipped with Clang 3.5.0 are not supported for lack of full C++14 support."
#   endif

#elif defined(__GLIBCXX__)

#   if __GLIBCXX__ < 20150422 // --> the libstdc++ shipped with GCC 5.1.0
#       warning "Versions of libstdc++ prior to the one shipped with GCC 5.1.0 are not supported for lack of full C++14 support."
#   endif

#   define PROXC_CONFIG_LIBSTDCXX

#elif defined(_MSC_VER)

#   define PROXC_CONFIG_LIBMSVCCXX

#else

#   warning "Your standard library was not detected properly and might not work for ProXC."

#endif

////////////////////////////////////////////////////////////////////////////////
// Detect 32- or 64-bit architecture
////////////////////////////////////////////////////////////////////////////////

#ifndef PROXC_ARCH

#if defined(__powerpc__) || defined(__ppc__) || defined(__PPC__) /* PowerPC */

#   if defined(__powerpc64__) || defined(__ppc64__) || defined(__PPC64__) || \
       defined(__64BIT__)     || defined(_LP64)     || defined(__LP64__) /* PowerPC 64-bit */

#       define PROXC_ARCH 64

#   else /* PowerPC 32-bit */

#       define PROXC_ARCH 32

#   endif

#elif defined(__x86_64__) || defined(_M_X64) /* x86 64-bit */

#   define PROXC_ARCH 64

#elif defined(__i386) || defined(_M_IX86) /* x86 32-bit */

#   define PROXC_ARCH 32

#elif defined(_WIN32) || defined(_WIN64) /* Windows */

#   if defined(_WIN64) /* Windows 64-bit */

#       define PROXC_ARCH 64

#   else /* Windows 32-bit */

#       define PROXC_ARCH 32

#   endif

#else /* Unknown architecture */

#   define PROXC_ARCH 64
#   warning "Architecture was neither correctly determined nor specified. Defaults to 64-bit. This can be set with -DPROXC_ARCH={32/64}, for 32-bit or 64-bit respectively."

#endif

#endif // PROXC_ARCH

static_assert(((PROXC_ARCH) == 32) || ((PROXC_ARCH) == 64), "Architecture specified by PROXC_ARCH only supports 32 or 64 value.");

// cache alignment and cachelines
static constexpr std::size_t cache_alignment{ PROXC_ARCH };
static constexpr std::size_t cacheline_length{ PROXC_ARCH };

////////////////////////////////////////////////////////////////////////////////
// Namespace macros
////////////////////////////////////////////////////////////////////////////////

#define PROXC_NAMESPACE_BEGIN namespace proxc {

#define PROXC_NAMESPACE_END }

<|endoftext|>


<commit_before>//----------------------------------------------------------------------------
/// \file  pidfile.hpp
//----------------------------------------------------------------------------
/// \brief Creates and manages a file containing a process identifier.
/// This file is necessary for ease of administration of daemon processes.
//----------------------------------------------------------------------------
// Copyright (c) 2010 Serge Aleynikov <saleyn@gmail.com>
// Created: 2011-02-18
//----------------------------------------------------------------------------
/*
***** BEGIN LICENSE BLOCK *****

This file is part of the utxx open-source project.

Copyright (C) 2010 Serge Aleynikov <saleyn@gmail.com>

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; either
version 2.1 of the License, or (at your option) any later version.

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

***** END LICENSE BLOCK *****
*/
#ifndef _UTXX_PIDFILE_HPP_
#define _UTXX_PIDFILE_HPP_

#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <utxx/error.hpp>
#include <utxx/convert.hpp>

namespace utxx {

/**
 * PID file manager
 * Used to crete a file containing process identifier of currently
 * running process.  This file is used by administration scripts in
 * order to be able to kill the process by pid.
 */
struct pid_file {
    explicit pid_file(const char* a_filename, mode_t a_mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP)
        throw (io_error)
        : m_filename(a_filename)
    {
        m_fd = open(a_filename, O_CREAT | O_RDWR | O_TRUNC, a_mode);
        if (m_fd < 0)
            throw io_error(errno, "Cannot open file:", a_filename);
        pid_t pid = ::getpid();
        std::string s = int_to_string(pid);
        if (::write(m_fd, s.c_str(), s.size()) < 0)
            throw io_error(errno, "Cannot write to file:", a_filename);
    }

    ~pid_file() {
        if (m_fd >= 0)
            ::close(m_fd);
        ::unlink(m_filename.c_str());
    }
private:
    std::string m_filename;
    int m_fd;
};

} // namespace utxx

#endif // _UTXX_PIDFILE_HPP_

<commit_msg>Update pidfile.hpp<commit_after>//----------------------------------------------------------------------------
/// \file  pidfile.hpp
//----------------------------------------------------------------------------
/// \brief Creates and manages a file containing a process identifier.
/// This file is necessary for ease of administration of daemon processes.
//----------------------------------------------------------------------------
// Copyright (c) 2010 Serge Aleynikov <saleyn@gmail.com>
// Created: 2011-02-18
//----------------------------------------------------------------------------
/*
***** BEGIN LICENSE BLOCK *****

This file is part of the utxx open-source project.

Copyright (C) 2010 Serge Aleynikov <saleyn@gmail.com>

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; either
version 2.1 of the License, or (at your option) any later version.

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

***** END LICENSE BLOCK *****
*/
#pragma once

#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <utxx/error.hpp>
#include <utxx/convert.hpp>

namespace utxx {

/**
 * PID file manager
 * Used to crete a file containing process identifier of currently
 * running process.  This file is used by administration scripts in
 * order to be able to kill the process by pid.
 */
struct pid_file {
    explicit pid_file(const char* a_filename, mode_t a_mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP)
        throw (io_error)
        : m_filename(a_filename)
    {
        m_fd = open(a_filename, O_CREAT | O_RDWR | O_TRUNC, a_mode);
        if (m_fd < 0)
            throw io_error(errno, "Cannot open file:", a_filename);
        pid_t pid = ::getpid();
        std::string s = int_to_string(pid);
        if (::write(m_fd, s.c_str(), s.size()) < 0)
            throw io_error(errno, "Cannot write to file:", a_filename);
    }

    ~pid_file() {
        if (m_fd >= 0)
            ::close(m_fd);
        ::unlink(m_filename.c_str());
    }
private:
    std::string m_filename;
    int m_fd;
};

} // namespace utxx
<|endoftext|>


<commit_before>#include "indexer/feature_data.hpp"
#include "indexer/feature_impl.hpp"
#include "indexer/classificator.hpp"
#include "indexer/feature.hpp"

#include "base/assert.hpp"
#include "base/stl_add.hpp"

#include "std/algorithm.hpp"
#include "std/bind.hpp"
#include "std/vector.hpp"

using namespace feature;

////////////////////////////////////////////////////////////////////////////////////
// TypesHolder implementation
////////////////////////////////////////////////////////////////////////////////////

TypesHolder::TypesHolder(FeatureBase const & f)
: m_size(0), m_geoType(f.GetFeatureType())
{
  f.ForEachType([this](uint32_t type)
  {
    this->operator()(type);
  });
}

string TypesHolder::DebugPrint() const
{
  Classificator const & c = classif();

  string s;
  for (uint32_t t : *this)
    s += c.GetFullObjectName(t) + "  ";
  return s;
}

void TypesHolder::Remove(uint32_t t)
{
  (void) RemoveIf(EqualFunctor<uint32_t>(t));
}

bool TypesHolder::Equals(TypesHolder const & other) const
{
  vector<uint32_t> my(this->begin(), this->end());
  vector<uint32_t> his(other.begin(), other.end());

  sort(::begin(my), ::end(my));
  sort(::begin(his), ::end(his));

  return my == his;
}

namespace
{

class UselessTypesChecker
{
  vector<uint32_t> m_types;
  size_t m_count1;

  template <size_t N, size_t M>
  void AddTypes(char const * (&arr)[N][M])
  {
    Classificator const & c = classif();

    for (size_t i = 0; i < N; ++i)
      m_types.push_back(c.GetTypeByPath(vector<string>(arr[i], arr[i] + M)));
  }

public:
  UselessTypesChecker()
  {
    // Fill types that will be taken into account last,
    // when we have many types for POI.

    // 1-arity
    char const * arr1[][1] = {
      { "building" },
      { "hwtag" },
      { "internet_access" },
    };

    AddTypes(arr1);
    m_count1 = m_types.size();

    // 2-arity
    char const * arr2[][2] = {
      { "amenity", "atm" }
    };

    AddTypes(arr2);
  }

  bool operator() (uint32_t t) const
  {
    auto const end1 = m_types.begin() + m_count1;

    // check 2-arity types
    ftype::TruncValue(t, 2);
    if (find(end1, m_types.end(), t) != m_types.end())
      return true;

    // check 1-arity types
    ftype::TruncValue(t, 1);
    if (find(m_types.begin(), end1, t) != end1)
      return true;

    return false;
  }
};

}  // namespace

namespace feature
{
uint8_t CalculateHeader(uint32_t const typesCount, uint8_t const headerGeomType,
                        FeatureParamsBase const & params)
{
  ASSERT(typesCount != 0, ("Feature should have at least one type."));
  uint8_t header = static_cast<uint8_t>(typesCount - 1);

  if (!params.name.IsEmpty())
    header |= HEADER_HAS_NAME;

  if (params.layer != 0)
    header |= HEADER_HAS_LAYER;

  header |= headerGeomType;

  // Geometry type for additional info is only one.
  switch (headerGeomType)
  {
  case HEADER_GEOM_POINT:
    if (params.rank != 0)
      header |= HEADER_HAS_ADDINFO;
    break;
  case HEADER_GEOM_LINE:
    if (!params.ref.empty())
      header |= HEADER_HAS_ADDINFO;
    break;
  case HEADER_GEOM_AREA:
  case HEADER_GEOM_POINT_EX:
    if (!params.house.IsEmpty())
      header |= HEADER_HAS_ADDINFO;
    break;
  }

  return header;
}
}  // namespace feature

void TypesHolder::SortBySpec()
{
  if (m_size < 2)
    return;

  // Put "very common" types to the end of possible PP-description types.
  static UselessTypesChecker checker;
  (void) RemoveIfKeepValid(m_types, m_types + m_size, bind<bool>(cref(checker), _1));
}

////////////////////////////////////////////////////////////////////////////////////
// FeatureParamsBase implementation
////////////////////////////////////////////////////////////////////////////////////

void FeatureParamsBase::MakeZero()
{
  layer = 0;
  rank = 0;
  ref.clear();
  house.Clear();
  name.Clear();
}

bool FeatureParamsBase::operator == (FeatureParamsBase const & rhs) const
{
  return (name == rhs.name && house == rhs.house && ref == rhs.ref &&
          layer == rhs.layer && rank == rhs.rank);
}

bool FeatureParamsBase::CheckValid() const
{
   CHECK(layer > LAYER_LOW && layer < LAYER_HIGH, ());
   return true;
}

string FeatureParamsBase::DebugString() const
{
  string const utf8name = DebugPrint(name);
  return ((!utf8name.empty() ? "Name:" + utf8name : "") +
          (rank != 0 ? " Rank:" + DebugPrint(rank) : "") +
          (!house.IsEmpty() ? " House:" + house.Get() : "") +
          (!ref.empty() ? " Ref:" + ref : ""));
}

bool FeatureParamsBase::IsEmptyNames() const
{
  return name.IsEmpty() && house.IsEmpty() && ref.empty();
}

namespace
{

// Most used dummy values are taken from
// http://taginfo.openstreetmap.org/keys/addr%3Ahousename#values
bool IsDummyName(string const & s)
{
  return (s.empty() ||
          s == "Bloc" || s == "bloc" ||
          s == "жилой дом" ||
          s == "Edificio" || s == "edificio");
}

}

/////////////////////////////////////////////////////////////////////////////////////////
// FeatureParams implementation
/////////////////////////////////////////////////////////////////////////////////////////

bool FeatureParams::AddName(string const & lang, string const & s)
{
  if (IsDummyName(s))
    return false;

  // The "default" new name will replace the old one if any (e.g. from AddHouseName call).
  name.AddString(lang, s);
  return true;
}

bool FeatureParams::AddHouseName(string const & s)
{
  if (IsDummyName(s) || name.FindString(s) != StringUtf8Multilang::UNSUPPORTED_LANGUAGE_CODE)
    return false;

  // Most names are house numbers by statistics.
  if (house.IsEmpty() && AddHouseNumber(s))
    return true;

  // Add as a default name if we don't have it yet.
  string dummy;
  if (!name.GetString(StringUtf8Multilang::DEFAULT_CODE, dummy))
  {
    name.AddString(StringUtf8Multilang::DEFAULT_CODE, s);
    return true;
  }

  return false;
}

bool FeatureParams::AddHouseNumber(string const & ss)
{
  if (!feature::IsHouseNumber(ss))
    return false;

  // Remove trailing zero's from house numbers.
  // It's important for debug checks of serialized-deserialized feature.
  string s(ss);
  uint64_t n;
  if (strings::to_uint64(s, n))
    s = strings::to_string(n);

  house.Set(s);
  return true;
}

void FeatureParams::AddStreet(string s)
{
  // Replace \n with spaces because we write addresses to txt file.
  replace(s.begin(), s.end(), '\n', ' ');

  m_addrTags.Add(AddressData::STREET, s);
}

void FeatureParams::AddAddress(string const & s)
{
  size_t i = s.find_first_of("\t ");
  if (i != string::npos)
  {
    string const house = s.substr(0, i);
    if (feature::IsHouseNumber(house))
    {
      AddHouseNumber(house);
      i = s.find_first_not_of("\t ", i);
    }
    else
    {
      i = 0;
    }
  }
  else
  {
    i = 0;
  }

  AddStreet(s.substr(i));
}

void FeatureParams::AddPlace(string const & s)
{
  m_addrTags.Add(AddressData::PLACE, s);
}

void FeatureParams::AddPostcode(string const & s)
{
  m_addrTags.Add(AddressData::POSTCODE, s);
}

bool FeatureParams::FormatFullAddress(m2::PointD const & pt, string & res) const
{
  string const street = GetStreet();
  if (!street.empty() && !house.IsEmpty())
  {
    res = street + "|" + house.Get() + "|"
        + strings::to_string_dac(MercatorBounds::YToLat(pt.y), 8) + "|"
        + strings::to_string_dac(MercatorBounds::XToLon(pt.x), 8) + '\n';
    return true;
  }

  return false;
}

string FeatureParams::GetStreet() const
{
  return m_addrTags.Get(AddressData::STREET);
}

void FeatureParams::SetGeomType(feature::EGeomType t)
{
  switch (t)
  {
  case GEOM_POINT: m_geomType = HEADER_GEOM_POINT; break;
  case GEOM_LINE: m_geomType = HEADER_GEOM_LINE; break;
  case GEOM_AREA: m_geomType = HEADER_GEOM_AREA; break;
  default: ASSERT(false, ());
  }
}

void FeatureParams::SetGeomTypePointEx()
{
  ASSERT(m_geomType == HEADER_GEOM_POINT || m_geomType == HEADER_GEOM_POINT_EX, ());
  ASSERT(!house.IsEmpty(), ());

  m_geomType = HEADER_GEOM_POINT_EX;
}

feature::EGeomType FeatureParams::GetGeomType() const
{
  CHECK_NOT_EQUAL(m_geomType, 0xFF, ());
  switch (m_geomType)
  {
  case HEADER_GEOM_LINE: return GEOM_LINE;
  case HEADER_GEOM_AREA: return GEOM_AREA;
  default: return GEOM_POINT;
  }
}

uint8_t FeatureParams::GetTypeMask() const
{
  CHECK_NOT_EQUAL(m_geomType, 0xFF, ());
  return m_geomType;
}

void FeatureParams::SetRwSubwayType(char const * cityName)
{
  Classificator const & c = classif();

  static uint32_t const src = c.GetTypeByPath({"railway", "station"});
  uint32_t const dest = c.GetTypeByPath({"railway", "station", "subway", cityName});

  for (size_t i = 0; i < m_Types.size(); ++i)
  {
    uint32_t t = m_Types[i];
    ftype::TruncValue(t, 2);
    if (t == src)
    {
      m_Types[i] = dest;
      break;
    }
  }
}

void FeatureParams::AddTypes(FeatureParams const & rhs, uint32_t skipType2)
{
  if (skipType2 == 0)
  {
    m_Types.insert(m_Types.end(), rhs.m_Types.begin(), rhs.m_Types.end());
  }
  else
  {
    for (size_t i = 0; i < rhs.m_Types.size(); ++i)
    {
      uint32_t t = rhs.m_Types[i];
      ftype::TruncValue(t, 2);
      if (t != skipType2)
        m_Types.push_back(rhs.m_Types[i]);
    }
  }
}

bool FeatureParams::FinishAddingTypes()
{
  static uint32_t const boundary = classif().GetTypeByPath({ "boundary", "administrative" });

  vector<uint32_t> newTypes;
  newTypes.reserve(m_Types.size());

  for (size_t i = 0; i < m_Types.size(); ++i)
  {
    uint32_t candidate = m_Types[i];

    // Assume that classificator types are equal if they are equal for 2-arity dimension
    // (e.g. "place-city-capital" is equal to "place-city" and we leave the longest one "place-city-capital").
    // The only exception is "boundary-administrative" type.

    uint32_t type = m_Types[i];
    ftype::TruncValue(type, 2);
    if (type != boundary)
    {
      // Find all equal types (2-arity).
      auto j = RemoveIfKeepValid(m_Types.begin() + i + 1, m_Types.end(), [type] (uint32_t t)
      {
        ftype::TruncValue(t, 2);
        return (type == t);
      });

      // Choose the best type from equals by arity level.
      for (auto k = j; k != m_Types.end(); ++k)
        if (ftype::GetLevel(*k) > ftype::GetLevel(candidate))
          candidate = *k;

      // Delete equal types.
      m_Types.erase(j, m_Types.end());
    }

    newTypes.push_back(candidate);
  }

  // Remove duplicated types.
  sort(newTypes.begin(), newTypes.end());
  newTypes.erase(unique(newTypes.begin(), newTypes.end()), newTypes.end());

  m_Types.swap(newTypes);

  if (m_Types.size() > max_types_count)
    m_Types.resize(max_types_count);

  return !m_Types.empty();
}

void FeatureParams::SetType(uint32_t t)
{
  m_Types.clear();
  m_Types.push_back(t);
}

bool FeatureParams::PopAnyType(uint32_t & t)
{
  CHECK(!m_Types.empty(), ());
  t = m_Types.back();
  m_Types.pop_back();
  return m_Types.empty();
}

bool FeatureParams::PopExactType(uint32_t t)
{
  m_Types.erase(remove(m_Types.begin(), m_Types.end(), t), m_Types.end());
  return m_Types.empty();
}

bool FeatureParams::IsTypeExist(uint32_t t) const
{
  return (find(m_Types.begin(), m_Types.end(), t) != m_Types.end());
}

uint32_t FeatureParams::FindType(uint32_t comp, uint8_t level) const
{
  for (uint32_t const type : m_Types)
  {
    uint32_t t = type;
    ftype::TruncValue(t, level);
    if (t == comp)
      return type;
  }
  return ftype::GetEmptyValue();
}

bool FeatureParams::CheckValid() const
{
  CHECK(!m_Types.empty() && m_Types.size() <= max_types_count, ());
  CHECK_NOT_EQUAL(m_geomType, 0xFF, ());

  return FeatureParamsBase::CheckValid();
}

uint8_t FeatureParams::GetHeader() const
{
  return CalculateHeader(m_Types.size(), GetTypeMask(), *this);
}

uint32_t FeatureParams::GetIndexForType(uint32_t t)
{
  return classif().GetIndexForType(t);
}

uint32_t FeatureParams::GetTypeForIndex(uint32_t i)
{
  return classif().GetTypeForIndex(i);
}

string DebugPrint(FeatureParams const & p)
{
  Classificator const & c = classif();

  string res = "Types";
  for (size_t i = 0; i < p.m_Types.size(); ++i)
    res += (" : " + c.GetReadableObjectName(p.m_Types[i]));

  return (res + p.DebugString());
}
<commit_msg>Added more building “useless” types.<commit_after>#include "indexer/feature_data.hpp"
#include "indexer/feature_impl.hpp"
#include "indexer/classificator.hpp"
#include "indexer/feature.hpp"

#include "base/assert.hpp"
#include "base/stl_add.hpp"

#include "std/algorithm.hpp"
#include "std/bind.hpp"
#include "std/vector.hpp"

using namespace feature;

////////////////////////////////////////////////////////////////////////////////////
// TypesHolder implementation
////////////////////////////////////////////////////////////////////////////////////

TypesHolder::TypesHolder(FeatureBase const & f)
: m_size(0), m_geoType(f.GetFeatureType())
{
  f.ForEachType([this](uint32_t type)
  {
    this->operator()(type);
  });
}

string TypesHolder::DebugPrint() const
{
  Classificator const & c = classif();

  string s;
  for (uint32_t t : *this)
    s += c.GetFullObjectName(t) + "  ";
  return s;
}

void TypesHolder::Remove(uint32_t t)
{
  (void) RemoveIf(EqualFunctor<uint32_t>(t));
}

bool TypesHolder::Equals(TypesHolder const & other) const
{
  vector<uint32_t> my(this->begin(), this->end());
  vector<uint32_t> his(other.begin(), other.end());

  sort(::begin(my), ::end(my));
  sort(::begin(his), ::end(his));

  return my == his;
}

namespace
{

class UselessTypesChecker
{
  vector<uint32_t> m_types;
  size_t m_count1;

  template <size_t N, size_t M>
  void AddTypes(char const * (&arr)[N][M])
  {
    Classificator const & c = classif();

    for (size_t i = 0; i < N; ++i)
      m_types.push_back(c.GetTypeByPath(vector<string>(arr[i], arr[i] + M)));
  }

public:
  UselessTypesChecker()
  {
    // Fill types that will be taken into account last,
    // when we have many types for POI.

    // 1-arity
    char const * arr1[][1] = {
      { "building" },
      { "building:part" },
      { "hwtag" },
      { "internet_access" },
    };

    AddTypes(arr1);
    m_count1 = m_types.size();

    // 2-arity
    char const * arr2[][2] = {
      { "amenity", "atm" },
      { "building", "address" },
    };

    AddTypes(arr2);
  }

  bool operator() (uint32_t t) const
  {
    auto const end1 = m_types.begin() + m_count1;

    // check 2-arity types
    ftype::TruncValue(t, 2);
    if (find(end1, m_types.end(), t) != m_types.end())
      return true;

    // check 1-arity types
    ftype::TruncValue(t, 1);
    if (find(m_types.begin(), end1, t) != end1)
      return true;

    return false;
  }
};

}  // namespace

namespace feature
{
uint8_t CalculateHeader(uint32_t const typesCount, uint8_t const headerGeomType,
                        FeatureParamsBase const & params)
{
  ASSERT(typesCount != 0, ("Feature should have at least one type."));
  uint8_t header = static_cast<uint8_t>(typesCount - 1);

  if (!params.name.IsEmpty())
    header |= HEADER_HAS_NAME;

  if (params.layer != 0)
    header |= HEADER_HAS_LAYER;

  header |= headerGeomType;

  // Geometry type for additional info is only one.
  switch (headerGeomType)
  {
  case HEADER_GEOM_POINT:
    if (params.rank != 0)
      header |= HEADER_HAS_ADDINFO;
    break;
  case HEADER_GEOM_LINE:
    if (!params.ref.empty())
      header |= HEADER_HAS_ADDINFO;
    break;
  case HEADER_GEOM_AREA:
  case HEADER_GEOM_POINT_EX:
    if (!params.house.IsEmpty())
      header |= HEADER_HAS_ADDINFO;
    break;
  }

  return header;
}
}  // namespace feature

void TypesHolder::SortBySpec()
{
  if (m_size < 2)
    return;

  // Put "very common" types to the end of possible PP-description types.
  static UselessTypesChecker checker;
  (void) RemoveIfKeepValid(m_types, m_types + m_size, bind<bool>(cref(checker), _1));
}

////////////////////////////////////////////////////////////////////////////////////
// FeatureParamsBase implementation
////////////////////////////////////////////////////////////////////////////////////

void FeatureParamsBase::MakeZero()
{
  layer = 0;
  rank = 0;
  ref.clear();
  house.Clear();
  name.Clear();
}

bool FeatureParamsBase::operator == (FeatureParamsBase const & rhs) const
{
  return (name == rhs.name && house == rhs.house && ref == rhs.ref &&
          layer == rhs.layer && rank == rhs.rank);
}

bool FeatureParamsBase::CheckValid() const
{
   CHECK(layer > LAYER_LOW && layer < LAYER_HIGH, ());
   return true;
}

string FeatureParamsBase::DebugString() const
{
  string const utf8name = DebugPrint(name);
  return ((!utf8name.empty() ? "Name:" + utf8name : "") +
          (rank != 0 ? " Rank:" + DebugPrint(rank) : "") +
          (!house.IsEmpty() ? " House:" + house.Get() : "") +
          (!ref.empty() ? " Ref:" + ref : ""));
}

bool FeatureParamsBase::IsEmptyNames() const
{
  return name.IsEmpty() && house.IsEmpty() && ref.empty();
}

namespace
{

// Most used dummy values are taken from
// http://taginfo.openstreetmap.org/keys/addr%3Ahousename#values
bool IsDummyName(string const & s)
{
  return (s.empty() ||
          s == "Bloc" || s == "bloc" ||
          s == "жилой дом" ||
          s == "Edificio" || s == "edificio");
}

}

/////////////////////////////////////////////////////////////////////////////////////////
// FeatureParams implementation
/////////////////////////////////////////////////////////////////////////////////////////

bool FeatureParams::AddName(string const & lang, string const & s)
{
  if (IsDummyName(s))
    return false;

  // The "default" new name will replace the old one if any (e.g. from AddHouseName call).
  name.AddString(lang, s);
  return true;
}

bool FeatureParams::AddHouseName(string const & s)
{
  if (IsDummyName(s) || name.FindString(s) != StringUtf8Multilang::UNSUPPORTED_LANGUAGE_CODE)
    return false;

  // Most names are house numbers by statistics.
  if (house.IsEmpty() && AddHouseNumber(s))
    return true;

  // Add as a default name if we don't have it yet.
  string dummy;
  if (!name.GetString(StringUtf8Multilang::DEFAULT_CODE, dummy))
  {
    name.AddString(StringUtf8Multilang::DEFAULT_CODE, s);
    return true;
  }

  return false;
}

bool FeatureParams::AddHouseNumber(string const & ss)
{
  if (!feature::IsHouseNumber(ss))
    return false;

  // Remove trailing zero's from house numbers.
  // It's important for debug checks of serialized-deserialized feature.
  string s(ss);
  uint64_t n;
  if (strings::to_uint64(s, n))
    s = strings::to_string(n);

  house.Set(s);
  return true;
}

void FeatureParams::AddStreet(string s)
{
  // Replace \n with spaces because we write addresses to txt file.
  replace(s.begin(), s.end(), '\n', ' ');

  m_addrTags.Add(AddressData::STREET, s);
}

void FeatureParams::AddAddress(string const & s)
{
  size_t i = s.find_first_of("\t ");
  if (i != string::npos)
  {
    string const house = s.substr(0, i);
    if (feature::IsHouseNumber(house))
    {
      AddHouseNumber(house);
      i = s.find_first_not_of("\t ", i);
    }
    else
    {
      i = 0;
    }
  }
  else
  {
    i = 0;
  }

  AddStreet(s.substr(i));
}

void FeatureParams::AddPlace(string const & s)
{
  m_addrTags.Add(AddressData::PLACE, s);
}

void FeatureParams::AddPostcode(string const & s)
{
  m_addrTags.Add(AddressData::POSTCODE, s);
}

bool FeatureParams::FormatFullAddress(m2::PointD const & pt, string & res) const
{
  string const street = GetStreet();
  if (!street.empty() && !house.IsEmpty())
  {
    res = street + "|" + house.Get() + "|"
        + strings::to_string_dac(MercatorBounds::YToLat(pt.y), 8) + "|"
        + strings::to_string_dac(MercatorBounds::XToLon(pt.x), 8) + '\n';
    return true;
  }

  return false;
}

string FeatureParams::GetStreet() const
{
  return m_addrTags.Get(AddressData::STREET);
}

void FeatureParams::SetGeomType(feature::EGeomType t)
{
  switch (t)
  {
  case GEOM_POINT: m_geomType = HEADER_GEOM_POINT; break;
  case GEOM_LINE: m_geomType = HEADER_GEOM_LINE; break;
  case GEOM_AREA: m_geomType = HEADER_GEOM_AREA; break;
  default: ASSERT(false, ());
  }
}

void FeatureParams::SetGeomTypePointEx()
{
  ASSERT(m_geomType == HEADER_GEOM_POINT || m_geomType == HEADER_GEOM_POINT_EX, ());
  ASSERT(!house.IsEmpty(), ());

  m_geomType = HEADER_GEOM_POINT_EX;
}

feature::EGeomType FeatureParams::GetGeomType() const
{
  CHECK_NOT_EQUAL(m_geomType, 0xFF, ());
  switch (m_geomType)
  {
  case HEADER_GEOM_LINE: return GEOM_LINE;
  case HEADER_GEOM_AREA: return GEOM_AREA;
  default: return GEOM_POINT;
  }
}

uint8_t FeatureParams::GetTypeMask() const
{
  CHECK_NOT_EQUAL(m_geomType, 0xFF, ());
  return m_geomType;
}

void FeatureParams::SetRwSubwayType(char const * cityName)
{
  Classificator const & c = classif();

  static uint32_t const src = c.GetTypeByPath({"railway", "station"});
  uint32_t const dest = c.GetTypeByPath({"railway", "station", "subway", cityName});

  for (size_t i = 0; i < m_Types.size(); ++i)
  {
    uint32_t t = m_Types[i];
    ftype::TruncValue(t, 2);
    if (t == src)
    {
      m_Types[i] = dest;
      break;
    }
  }
}

void FeatureParams::AddTypes(FeatureParams const & rhs, uint32_t skipType2)
{
  if (skipType2 == 0)
  {
    m_Types.insert(m_Types.end(), rhs.m_Types.begin(), rhs.m_Types.end());
  }
  else
  {
    for (size_t i = 0; i < rhs.m_Types.size(); ++i)
    {
      uint32_t t = rhs.m_Types[i];
      ftype::TruncValue(t, 2);
      if (t != skipType2)
        m_Types.push_back(rhs.m_Types[i]);
    }
  }
}

bool FeatureParams::FinishAddingTypes()
{
  static uint32_t const boundary = classif().GetTypeByPath({ "boundary", "administrative" });

  vector<uint32_t> newTypes;
  newTypes.reserve(m_Types.size());

  for (size_t i = 0; i < m_Types.size(); ++i)
  {
    uint32_t candidate = m_Types[i];

    // Assume that classificator types are equal if they are equal for 2-arity dimension
    // (e.g. "place-city-capital" is equal to "place-city" and we leave the longest one "place-city-capital").
    // The only exception is "boundary-administrative" type.

    uint32_t type = m_Types[i];
    ftype::TruncValue(type, 2);
    if (type != boundary)
    {
      // Find all equal types (2-arity).
      auto j = RemoveIfKeepValid(m_Types.begin() + i + 1, m_Types.end(), [type] (uint32_t t)
      {
        ftype::TruncValue(t, 2);
        return (type == t);
      });

      // Choose the best type from equals by arity level.
      for (auto k = j; k != m_Types.end(); ++k)
        if (ftype::GetLevel(*k) > ftype::GetLevel(candidate))
          candidate = *k;

      // Delete equal types.
      m_Types.erase(j, m_Types.end());
    }

    newTypes.push_back(candidate);
  }

  // Remove duplicated types.
  sort(newTypes.begin(), newTypes.end());
  newTypes.erase(unique(newTypes.begin(), newTypes.end()), newTypes.end());

  m_Types.swap(newTypes);

  if (m_Types.size() > max_types_count)
    m_Types.resize(max_types_count);

  return !m_Types.empty();
}

void FeatureParams::SetType(uint32_t t)
{
  m_Types.clear();
  m_Types.push_back(t);
}

bool FeatureParams::PopAnyType(uint32_t & t)
{
  CHECK(!m_Types.empty(), ());
  t = m_Types.back();
  m_Types.pop_back();
  return m_Types.empty();
}

bool FeatureParams::PopExactType(uint32_t t)
{
  m_Types.erase(remove(m_Types.begin(), m_Types.end(), t), m_Types.end());
  return m_Types.empty();
}

bool FeatureParams::IsTypeExist(uint32_t t) const
{
  return (find(m_Types.begin(), m_Types.end(), t) != m_Types.end());
}

uint32_t FeatureParams::FindType(uint32_t comp, uint8_t level) const
{
  for (uint32_t const type : m_Types)
  {
    uint32_t t = type;
    ftype::TruncValue(t, level);
    if (t == comp)
      return type;
  }
  return ftype::GetEmptyValue();
}

bool FeatureParams::CheckValid() const
{
  CHECK(!m_Types.empty() && m_Types.size() <= max_types_count, ());
  CHECK_NOT_EQUAL(m_geomType, 0xFF, ());

  return FeatureParamsBase::CheckValid();
}

uint8_t FeatureParams::GetHeader() const
{
  return CalculateHeader(m_Types.size(), GetTypeMask(), *this);
}

uint32_t FeatureParams::GetIndexForType(uint32_t t)
{
  return classif().GetIndexForType(t);
}

uint32_t FeatureParams::GetTypeForIndex(uint32_t i)
{
  return classif().GetTypeForIndex(i);
}

string DebugPrint(FeatureParams const & p)
{
  Classificator const & c = classif();

  string res = "Types";
  for (size_t i = 0; i < p.m_Types.size(); ++i)
    res += (" : " + c.GetReadableObjectName(p.m_Types[i]));

  return (res + p.DebugString());
}
<|endoftext|>