<commit_before>#ifndef _COMPASS_FIXTURES_H_
#define _COMPASS_FIXTURES_H_

#include <iostream>
#include <string>

#include "machine_info.hpp"

struct host_reference
{

  std::string	hostname		;

  std::string   expected_vendor         ;
  std::string   expected_brand          ;
  std::string   expected_device_name    ;
  bool      expected_has_sse	;
  bool      expected_has_sse2	;
  bool      expected_has_sse3	;
  bool      expected_has_sse4	;
  bool      expected_has_avx	;
  bool      expected_has_avx2	;
  int       expected_ncores		;

  int       expected_L1d_linesize		;
  int       expected_L2_linesize		;
  int       expected_L3_linesize		;

  int       expected_L1d_size_kB		;
  int       expected_L2_size_kB		;
  int       expected_L3_size_kB		;

  host_reference():
    hostname(compass::tests::hostname()),
    expected_vendor  (""),
    expected_brand   (""),
    expected_device_name   (""),
    expected_has_sse (false),
    expected_has_sse2(false),
    expected_has_sse3(false),
    expected_has_sse4(false),
    expected_has_avx (false),
    expected_has_avx2(false),
    expected_L1d_linesize(0) ,
    expected_L2_linesize(0) ,
    expected_L3_linesize(0) ,
    expected_L1d_size_kB(0) ,
    expected_L2_size_kB(0),
    expected_L3_size_kB(0),
    expected_ncores  (-1)
  {

    if(hostname.find("schorle") != std::string::npos){
      expected_vendor = "intel";
      expected_brand  = "Intel(R) Core(TM) i7-3520M CPU @ 2.90GHz";
      expected_device_name = "i7-3520M";
      expected_has_sse = true ;
      expected_has_sse2= true ;
      expected_has_sse3= true ;
      expected_has_sse4= true ;
      expected_has_avx = true ;
      expected_has_avx2= false ;
      expected_L1d_linesize= 64 ;
      expected_L2_linesize= 64 ;
      expected_L3_linesize= 64 ;
      expected_L1d_size_kB= 64 ;
      expected_L2_size_kB= 0 ;
      expected_L3_size_kB= 0 ;

      expected_ncores = 4;
    }

    //travis host
    if(hostname.find("-gce-") != std::string::npos){
      expected_vendor = "intel";
      expected_brand  = "Intel(R) Xeon(R) CPU @ 2.30GHz";
      expected_device_name = "";
      expected_has_sse = true ;
      expected_has_sse2= true ;
      expected_has_sse3= true ;
      expected_has_sse4= true ;
      expected_has_avx = true ;
      expected_has_avx2= true ;
      expected_ncores = 2;
    }

    //windows machine
    if (hostname.find("scicomp-pc-3") != std::string::npos) {
      expected_vendor = "intel";
      expected_brand = "Intel(R) Xeon(R) CPU E3-1245 v3 @ 3.40GHz";
      expected_device_name = "E3-1245v3";
      expected_has_sse = true;
      expected_has_sse2 = true;
      expected_has_sse3 = true;
      expected_has_sse4 = true;
      expected_has_avx = true;
      expected_has_avx2 = true;
      expected_ncores = 8;
    }

    //OSX machine
    if (hostname.find("recovery-station") != std::string::npos) {
      expected_vendor = "intel";
      expected_brand = "Intel(R) Core(TM) i5-4570 CPU @ 3.20GHz";
      expected_device_name = "i5-4570";
      expected_has_sse = true;
      expected_has_sse2 = true;
      expected_has_sse3 = true;
      expected_has_sse4 = true;
      expected_has_avx = true;
      expected_has_avx2 = true;
      expected_ncores = 4;
    }

    if(hostname.find("falcon2") == 0){
      expected_vendor = "intel";
      expected_brand = "Intel(R) Xeon(R) CPU E5-2670 v3 @ 2.30GHz";
      expected_device_name = "E5-2670v3";
      expected_has_sse = true;
      expected_has_sse2 = true;
      expected_has_sse3 = true;
      expected_has_sse4 = true;
      expected_has_avx = true;
      expected_has_avx2 = true;
      expected_ncores = 24;

    }

    if(hostname.find("talisker") == 0){
      expected_vendor = "intel";
      expected_brand = "Intel(R) Xeon(R) CPU E5-2698 v4 @ 2.20GHz";
      expected_device_name = "E5-2698v4";
      expected_has_sse = true;
      expected_has_sse2 = true;
      expected_has_sse3 = true;
      expected_has_sse4 = true;
      expected_has_avx = true;
      expected_has_avx2 = true;
      expected_ncores = 40;

    }
  }

};

#endif /* _COMPASS_FIXTURES_H_ */
<commit_msg>added values for local machines<commit_after>#ifndef _COMPASS_FIXTURES_H_
#define _COMPASS_FIXTURES_H_

#include <iostream>
#include <string>

#include "machine_info.hpp"

struct host_reference
{

  std::string	hostname		;

  std::string   expected_vendor         ;
  std::string   expected_brand          ;
  std::string   expected_device_name    ;
  bool      expected_has_sse	;
  bool      expected_has_sse2	;
  bool      expected_has_sse3	;
  bool      expected_has_sse4	;
  bool      expected_has_avx	;
  bool      expected_has_avx2	;
  int       expected_ncores		;

  int       expected_L1d_linesize		;
  int       expected_L2_linesize		;
  int       expected_L3_linesize		;

  int       expected_L1d_size_kB		;
  int       expected_L2_size_kB		;
  int       expected_L3_size_kB		;

  host_reference():
    hostname(compass::tests::hostname()),
    expected_vendor  (""),
    expected_brand   (""),
    expected_device_name   (""),
    expected_has_sse (false),
    expected_has_sse2(false),
    expected_has_sse3(false),
    expected_has_sse4(false),
    expected_has_avx (false),
    expected_has_avx2(false),
    expected_L1d_linesize(0) ,
    expected_L2_linesize(0) ,
    expected_L3_linesize(0) ,
    expected_L1d_size_kB(0) ,
    expected_L2_size_kB(0),
    expected_L3_size_kB(0),
    expected_ncores  (-1)
  {

    if(hostname.find("schorle") != std::string::npos){
      expected_vendor = "intel";
      expected_brand  = "Intel(R) Core(TM) i7-3520M CPU @ 2.90GHz";
      expected_device_name = "i7-3520M";
      expected_has_sse = true ;
      expected_has_sse2= true ;
      expected_has_sse3= true ;
      expected_has_sse4= true ;
      expected_has_avx = true ;
      expected_has_avx2= false ;

      //check by `cat /sys/devices/system/cpu/cpu0/cache/index0/coherency_line_size`
      expected_L1d_linesize= 64 ;
      expected_L2_linesize= 64 ;
      expected_L3_linesize= 64 ;
      //check by `cat /sys/devices/system/cpu/cpu0/cache/index0/size`
      expected_L1d_size_kB= 32 ;
      expected_L2_size_kB= 256;
      expected_L3_size_kB= 4096 ;

      expected_ncores = 4;
    }

    //travis host
    if(hostname.find("-gce-") != std::string::npos){
      expected_vendor = "intel";
      expected_brand  = "Intel(R) Xeon(R) CPU @ 2.30GHz";
      expected_device_name = "";
      expected_has_sse = true ;
      expected_has_sse2= true ;
      expected_has_sse3= true ;
      expected_has_sse4= true ;
      expected_has_avx = true ;
      expected_has_avx2= true ;
      expected_ncores = 2;
    }

    //windows machine
    if (hostname.find("scicomp-pc-3") != std::string::npos) {
      expected_vendor = "intel";
      expected_brand = "Intel(R) Xeon(R) CPU E3-1245 v3 @ 3.40GHz";
      expected_device_name = "E3-1245v3";
      expected_has_sse = true;
      expected_has_sse2 = true;
      expected_has_sse3 = true;
      expected_has_sse4 = true;
      expected_has_avx = true;
      expected_has_avx2 = true;

      //check by `cat /sys/devices/system/cpu/cpu0/cache/index0/coherency_line_size`
      expected_L1d_linesize= 64 ;
      expected_L2_linesize= 64 ;
      expected_L3_linesize= 64 ;
      //check by `cat /sys/devices/system/cpu/cpu0/cache/index0/size`
      expected_L1d_size_kB= 32 ;
      expected_L2_size_kB= 256;
      expected_L3_size_kB= 2*4096 ;

      expected_ncores = 8;
    }

    //OSX machine
    if (hostname.find("recovery-station") != std::string::npos) {
      expected_vendor = "intel";
      expected_brand = "Intel(R) Core(TM) i5-4570 CPU @ 3.20GHz";
      expected_device_name = "i5-4570";
      expected_has_sse = true;
      expected_has_sse2 = true;
      expected_has_sse3 = true;
      expected_has_sse4 = true;
      expected_has_avx = true;
      expected_has_avx2 = true;

      //check by `cat /sys/devices/system/cpu/cpu0/cache/index0/coherency_line_size`
      expected_L1d_linesize= 64 ;
      expected_L2_linesize= 64 ;
      expected_L3_linesize= 64 ;
      //check by `cat /sys/devices/system/cpu/cpu0/cache/index0/size`
      expected_L1d_size_kB= 32 ;
      expected_L2_size_kB= 256;
      expected_L3_size_kB= 6*1024 ;

      expected_ncores = 4;
    }

    //centos
    if(hostname.find("falcon2") == 0){
      expected_vendor = "intel";
      expected_brand = "Intel(R) Xeon(R) CPU E5-2670 v3 @ 2.30GHz";
      expected_device_name = "E5-2670v3";
      expected_has_sse = true;
      expected_has_sse2 = true;
      expected_has_sse3 = true;
      expected_has_sse4 = true;
      expected_has_avx = true;
      expected_has_avx2 = true;
      //check by `cat /sys/devices/system/cpu/cpu0/cache/index0/coherency_line_size`
      expected_L1d_linesize= 64 ;
      expected_L2_linesize= 64 ;
      expected_L3_linesize= 64 ;
      //check by `cat /sys/devices/system/cpu/cpu0/cache/index0/size`
      expected_L1d_size_kB= 32 ;
      expected_L2_size_kB= 256;
      expected_L3_size_kB= 30720;

      expected_ncores = 24;

    }

    if(hostname.find("talisker") == 0){
      expected_vendor = "intel";
      expected_brand = "Intel(R) Xeon(R) CPU E5-2698 v4 @ 2.20GHz";
      expected_device_name = "E5-2698v4";
      expected_has_sse = true;
      expected_has_sse2 = true;
      expected_has_sse3 = true;
      expected_has_sse4 = true;
      expected_has_avx = true;
      expected_has_avx2 = true;

      //check by `cat /sys/devices/system/cpu/cpu0/cache/index0/coherency_line_size`
      expected_L1d_linesize= 64 ;
      expected_L2_linesize= 64 ;
      expected_L3_linesize= 64 ;
      //check by `cat /sys/devices/system/cpu/cpu0/cache/index0/size`
      expected_L1d_size_kB= 32 ;
      expected_L2_size_kB= 256;
      expected_L3_size_kB= 51200;

      expected_ncores = 40;

    }
  }

};

#endif /* _COMPASS_FIXTURES_H_ */
<|endoftext|>


<commit_before>#ifndef VSMC_UTILITY_PROGRAM_OPTION_HPP
#define VSMC_UTILITY_PROGRAM_OPTION_HPP

#include <vsmc/internal/common.hpp>

namespace vsmc {

/// \brief Program opiton base class
/// \ingroup Option
class ProgramOptionBase
{
    public :

    virtual bool compare_set (const char *, const char *) = 0;
    virtual void print_help () const = 0;
    virtual ~ProgramOptionBase () {}
};

/// \brief Class that store an option and its default value
/// \ingroup Option
template <typename T>
class ProgramOption : public ProgramOptionBase
{
    public :

    /// \brief Value type of this option
    typedef T value_type;

    /// \brief Construct an option that can store a single value
    ///
    /// \param name Name of the option, on command name it shall be specified
    /// by --name
    /// \param desc A descritpion stream of the option
    /// \param ptr The destination that store the option value
    ProgramOption (const char *name, const char *desc, T *ptr) :
        name_(std::string("--") + name),
        desc_(desc), ptr_(ptr), vec_ptr_(VSMC_NULLPTR), has_default_(false) {}

    /// \brief Construct an option that can store multiple values
    ///
    /// \param name Name of the option, on command name it shall be specified
    /// by --name. The option can be specified multiple times on the command
    /// line. Each value will be stored within the vector
    /// \param desc A descritpion stream of the option
    /// \param ptr The destination that store the option value
    ProgramOption (const char *name, const char *desc, std::vector<T> *ptr) :
        name_(std::string("--") + name),
        desc_(desc), ptr_(VSMC_NULLPTR), vec_ptr_(ptr), has_default_(false) {}

    /// \brief Construct an option that can store a single value with a default
    /// value
    template <typename V>
    ProgramOption (const char *name, const char *desc, T *ptr, const V &val) :
        name_(std::string("--") + name),
        desc_(desc), ptr_(ptr), vec_ptr_(VSMC_NULLPTR),
        default_(static_cast<T>(val)), has_default_(true) {*ptr = default_;}

    /// \brief Construct an option that can store multiple values with a
    /// default value
    template <typename V>
    ProgramOption (const char *name, const char *desc, std::vector<T> *ptr,
            const V &val) :
        name_(std::string("--") + name),
        desc_(desc), ptr_(VSMC_NULLPTR), vec_ptr_(ptr),
        default_(static_cast<T>(val)), has_default_(true)
    {
        vec_ptr_->clear();
        vec_ptr_->push_back(default_);
    }

    /// \brief Compare an option name and set value if it is the same as the
    /// name of this option
    ///
    /// \param name Name of the specified opiton to be checked against this
    /// option
    /// \param sval A string contains the value, will be converted to this
    /// option's type
    bool compare_set (const char *name, const char *sval)
    {
        if (std::strcmp(name_.c_str(), name))
            return false;

        std::stringstream ss;
        ss << sval;
        T tval;
        ss >> tval;
        if (ss.fail()) {
            std::fprintf(stderr, "Invalid value for option %s: %s\n",
                    name_.c_str(), sval);
            return false;
        }

        if (ptr_) *ptr_ = tval;
        if (vec_ptr_) vec_ptr_->push_back(tval);

        return true;
    }

    /// \brief Print help information
    void print_help () const
    {
        std::cout << "  " << std::setw(20) << std::left << name_ << desc_;
        if (has_default_)
            std::cout << " (default: " << default_ << ")";
        std::cout << std::endl;
    }

    private :

    std::string name_;
    std::string desc_;
    T *const ptr_;
    std::vector<T> *const vec_ptr_;
    T default_;
    bool has_default_;
};

/// \brief A map of ProgramOption
/// \ingroup Option
///
/// \details
/// Basic example:
/// \code
/// int main (int argc, char **argv)
/// {
///     double Value1;
///     double Value2;
///     std::vector<double> Value3;
///     std::vector<double> Value4;
///     ProgramOptionMap Map;
///     Map.add<double>("option1", "option description string 1", &Value1);
///     Map.add<double>("option2", "option description string 2", &Value2);
///     Map.add<double>("option3", "option description string 3", &Value3);
///     Map.add<double>("option4", "option description string 4", &Value4, 401);
///     if (Map.process(argc, argv)) {
///         Map.print_help();
///         return 0;
///     }
///
///     std::cout << Value1 << std::endl;
///     std::cout << Value2 << std::endl;
///     for (std::size_t i = 0; i != Value3.size(); ++i)
///         std::cout << Value3[i] << std::endl;
///     for (std::size_t i = 0; i != Value4.size(); ++i)
///         std::cout << Value4[i] << std::endl;
/// }
/// \endcode
/// And if on the command line,
/// \code
/// ./prog --option1 101 --option2 201 --option2 202 --option3 301 --option3 202 --option4 402
/// \end
/// will produce the output
/// \code
/// 101
/// 202
/// 301
/// 302
/// 401
/// 402
/// \endcode
/// An option may be specified multiple times on the command line. If the
/// option's value type is a specialization of std::vector, then all values
/// will be stored. Otherwise only the last one will be stored. A default value
/// may be specified for an option. If an option's value type is a
/// specializaiton of std::vector, then values specified on the command line
/// will be appended to the destination vector instead of override the defualt
/// value.
///
/// If add an option with a name that already exists, then it overrides the
/// previous one
class ProgramOptionMap
{
    public :

    ~ProgramOptionMap ()
    {
        for (std::map<std::string, ProgramOptionBase *>::iterator
                iter = option_ptr_.begin();
                iter != option_ptr_.end(); ++iter) {
            delete iter->second;
        }
    }

    /// \brief Add an option
    ///
    /// \param name Name of the option, on command name it shall be specified
    /// by --name
    /// \param desc A descritpion stream of the option
    /// \param ptr The destination that store the option value
    template <typename T, typename Dest>
    ProgramOptionMap &add (const char *name, const char *desc, Dest *ptr)
    {
        const std::string oname(std::string("--") + name);
        ProgramOptionBase *optr = new ProgramOption<T>(name, desc, ptr);
        if (option_ptr_.count(oname) != 0)
            delete option_ptr_[oname];
        option_ptr_[oname] = optr;
        option_processed_[oname] = 0;

        return *this;
    }

    /// \brief Add an option with a default value
    template <typename T, typename Dest, typename V>
    ProgramOptionMap &add (const char *name, const char *desc, Dest *ptr,
            const V &val)
    {
        const std::string oname(std::string("--") + name);
        ProgramOptionBase *optr = new ProgramOption<T>(name, desc, ptr, val);
        if (option_ptr_.count(oname) != 0)
            delete option_ptr_[oname];
        option_ptr_[oname] = optr;
        option_processed_[oname] = 0;

        return *this;
    }

    ProgramOptionMap &remove (const char *name)
    {
        const std::string oname(std::string("--") + name);
        if (option_ptr_.count(oname) != 0) {
            delete option_ptr_[oname];
            option_ptr_.erase(oname);
            option_processed_.erase(oname);
        }

        return *this;
    }

    /// \brief Process the options
    ///
    /// \details
    /// If the option "--help" is given at the commad line, then this function
    /// does not process any other options. It merely process the options
    /// --help by printing the help information.
    ///
    /// \param argc The first argument of the `main` function
    /// \param argv The second argument of the `main` function
    ///
    /// \return `true` If the option `--help` has been specified on the command
    /// line. Otherwise `false`.
    bool process (int argc, const char **argv)
    {
        for (int ac = 1; ac != argc; ++ac) {
            if (!std::strcmp(argv[ac], "--help")) {
                for (std::map<std::string, ProgramOptionBase *>::iterator
                        iter = option_ptr_.begin();
                        iter != option_ptr_.end(); ++iter) {
                    iter->second->print_help();
                }
                return true;
            }
        }

        for (std::map<std::string, ProgramOptionBase *>::iterator
                iter = option_ptr_.begin();
                iter != option_ptr_.end(); ++iter) {
            for (int ac = 1; ac != argc; ++ac) {
                bool set = iter->second->compare_set(argv[ac], argv[ac + 1]);
                if (set) ++option_processed_[iter->first];
            }
        }

        return false;
    }

    /// \brief Process the options
    bool process (int argc, char **argv)
    {
        const char **cargv = new const char *[argc];
        for (int i = 0; i != argc; ++i)
            cargv[i] = argv[i];

        return process(argc, cargv);
    }

    /// \brief Count the number of occurence of an option on the command line
    /// given its name
    std::size_t count (const char *name) const
    {return option_processed_.find(std::string("--") + name)->second;}

    private :

    std::map<std::string, ProgramOptionBase *> option_ptr_;
    std::map<std::string, std::size_t> option_processed_;
};

} // namespace vsmc

#endif // VSMC_UTILITY_PROGRAM_OPTION_HPP
<commit_msg>improve program options<commit_after>#ifndef VSMC_UTILITY_PROGRAM_OPTION_HPP
#define VSMC_UTILITY_PROGRAM_OPTION_HPP

#include <vsmc/internal/common.hpp>

namespace vsmc {

/// \brief Program opiton base class
/// \ingroup Option
class ProgramOptionBase
{
    public :

    virtual bool set (const std::string &) = 0;
    virtual void print_help () const = 0;
    virtual ProgramOptionBase *clone () const = 0;
    virtual ~ProgramOptionBase () {}
};

/// \brief Class that store an option and its default value
/// \ingroup Option
template <typename T>
class ProgramOption : public ProgramOptionBase
{
    public :

    /// \brief Value type of this option
    typedef T value_type;

    /// \brief Construct an option that can store a single value
    ///
    /// \param oname Name of the option in the format `--name`
    /// \param desc A descritpion stream of the option
    /// \param ptr The destination that store the option value
    ProgramOption (const std::string &oname, const std::string &desc, T *ptr) :
        oname_(oname), desc_(desc), ptr_(ptr), vec_ptr_(VSMC_NULLPTR),
        has_default_(false) {}

    /// \brief Construct an option that can store multiple values
    ///
    /// \param oname Name of the option in the format `--name`. The option can
    /// be specified multiple times on the command line. Each value will be
    /// stored within the vector
    /// \param desc A descritpion stream of the option
    /// \param ptr The destination that store the option value
    ProgramOption (const std::string &oname, const std::string &desc,
            std::vector<T> *ptr) :
        oname_(oname), desc_(desc), ptr_(VSMC_NULLPTR), vec_ptr_(ptr),
        has_default_(false) {}

    /// \brief Construct an option that can store a single value with a default
    /// value
    template <typename V>
    ProgramOption (const std::string &oname, const std::string &desc,
            T *ptr, const V &val) :
        oname_(oname), desc_(desc), ptr_(ptr), vec_ptr_(VSMC_NULLPTR),
        default_(static_cast<T>(val)), has_default_(true) {*ptr = default_;}

    /// \brief Construct an option that can store multiple values with a
    /// default value
    template <typename V>
    ProgramOption (const std::string &oname, const std::string &desc,
            std::vector<T> *ptr, const V &val) :
        oname_(oname), desc_(desc), ptr_(VSMC_NULLPTR), vec_ptr_(ptr),
        default_(static_cast<T>(val)), has_default_(true)
    {vec_ptr_->push_back(default_);}

    bool set (const std::string &sval)
    {
        std::stringstream ss;
        ss << sval;
        T tval;
        ss >> tval;
        if (ss.fail()) {
            std::fprintf(stderr, "Invalid value for option %s: %s\n",
                    oname_.c_str(), sval.c_str());
            return false;
        }

        if (ptr_) *ptr_ = tval;
        if (vec_ptr_) vec_ptr_->push_back(tval);

        return true;
    }

    /// \brief Print help information
    void print_help () const
    {
        std::cout << "  " << std::setw(20) << std::left << oname_ << desc_;
        if (has_default_)
            std::cout << " (default: " << default_ << ")";
        std::cout << std::endl;
    }

    ProgramOptionBase *clone () const
    {
        ProgramOptionBase *ptr = new ProgramOption<T>(*this);

        return ptr;
    }

    private :

    std::string oname_;
    std::string desc_;
    T *const ptr_;
    std::vector<T> *const vec_ptr_;
    T default_;
    bool has_default_;
};

/// \brief A map of ProgramOption
/// \ingroup Option
///
/// \details
/// Basic example:
/// \code
/// int main (int argc, char **argv)
/// {
///     double Value1;
///     double Value2;
///     std::vector<double> Value3;
///     std::vector<double> Value4;
///     ProgramOptionMap Map;
///     Map.add<double>("option1", "option description string 1", &Value1);
///     Map.add<double>("option2", "option description string 2", &Value2);
///     Map.add<double>("option3", "option description string 3", &Value3);
///     Map.add<double>("option4", "option description string 4", &Value4, 401);
///     if (Map.process(argc, argv)) // Help info was printed
///         return 0;
///
///     std::cout << Value1 << std::endl;
///     std::cout << Value2 << std::endl;
///     for (std::size_t i = 0; i != Value3.size(); ++i)
///         std::cout << Value3[i] << std::endl;
///     for (std::size_t i = 0; i != Value4.size(); ++i)
///         std::cout << Value4[i] << std::endl;
/// }
/// \endcode
/// And if on the command line,
/// \code
/// ./prog --option1 101 --option2 201 --option2 202 --option3 301 --option3 202 --option4 402
/// \end
/// will produce the output
/// \code
/// 101
/// 202
/// 301
/// 302
/// 401
/// 402
/// \endcode
/// An option may be specified multiple times on the command line. If the
/// option's value type is a specialization of std::vector, then all values
/// will be stored. Otherwise only the last one will be stored. A default value
/// may be specified for an option. If an option's value type is a
/// specializaiton of std::vector, then values specified on the command line
/// will be appended to the destination vector instead of override the defualt
/// value.
///
/// If add an option with a name that already exists, then it overrides the
/// previous one
class ProgramOptionMap
{
    public :

    ProgramOptionMap () {}

    ProgramOptionMap (const ProgramOptionMap &other) :
        option_ptr_(other.option_ptr_), option_cnt_(other.option_cnt_)
    {
        for (std::map<std::string, ProgramOptionBase *>::iterator
                iter = option_ptr_.begin();
                iter != option_ptr_.end(); ++iter) {
            if (iter->second)
                iter->second = iter->second->clone();
        }
    }

    ProgramOptionMap &operator= (const ProgramOptionMap &other)
    {
        if (this != &other) {
            for (std::map<std::string, ProgramOptionBase *>::iterator
                    iter = option_ptr_.begin();
                    iter != option_ptr_.end(); ++iter) {
                if (iter->second)
                    delete iter->second;
            }

            option_ptr_ = other.option_ptr_;
            option_cnt_ = other.option_cnt_;

            for (std::map<std::string, ProgramOptionBase *>::iterator
                    iter = option_ptr_.begin();
                    iter != option_ptr_.end(); ++iter) {
                if (iter->second)
                    iter->second = iter->second->clone();
            }
        }

        return *this;
    }

    ~ProgramOptionMap ()
    {
        for (std::map<std::string, ProgramOptionBase *>::iterator
                iter = option_ptr_.begin();
                iter != option_ptr_.end(); ++iter) {
            if (iter->second)
                delete iter->second;
        }
    }

    /// \brief Add an option
    ///
    /// \param name Name of the option, on command name it shall be specified
    /// by --name
    /// \param desc A descritpion stream of the option
    /// \param ptr The destination that store the option value
    template <typename T, typename Dest>
    ProgramOptionMap &add (const std::string &name, const std::string &desc,
            Dest *ptr)
    {
        const std::string oname("--" + name);
        ProgramOptionBase *optr = new ProgramOption<T>(oname, desc, ptr);
        if (option_ptr_.count(oname) != 0)
            if (option_ptr_[oname])
                delete option_ptr_[oname];
        option_ptr_[oname] = optr;
        option_cnt_[oname] = 0;

        return *this;
    }

    /// \brief Add an option with a default value
    template <typename T, typename Dest, typename V>
    ProgramOptionMap &add (const std::string &name, const std::string &desc,
            Dest *ptr, const V &val)
    {
        const std::string oname("--" + name);
        ProgramOptionBase *optr = new ProgramOption<T>(oname, desc, ptr, val);
        if (option_ptr_.count(oname) != 0)
            if (option_ptr_[oname])
                delete option_ptr_[oname];
        option_ptr_[oname] = optr;
        option_cnt_[oname] = 0;

        return *this;
    }

    ProgramOptionMap &remove (const std::string &name)
    {
        const std::string oname("--" + name);
        if (option_ptr_.count(oname) != 0) {
            if (option_ptr_[oname])
                delete option_ptr_[oname];
            option_ptr_.erase(oname);
            option_cnt_.erase(oname);
        }

        return *this;
    }

    /// \brief Process the options
    ///
    /// \details
    /// If the option "--help" is given at the commad line, then this function
    /// does not process any other options. It merely process the options
    /// --help by printing the help information.
    ///
    /// \param argc The first argument of the `main` function
    /// \param argv The second argument of the `main` function
    ///
    /// \return `true` If the option `--help` has been specified on the command
    /// line. Otherwise `false`.
    bool process (int argc, const char **argv)
    {
        for (int ac = 1; ac != argc; ++ac) {
            if (!std::strcmp(argv[ac], "--help")) {
                for (std::map<std::string, ProgramOptionBase *>::iterator
                        iter = option_ptr_.begin();
                        iter != option_ptr_.end(); ++iter) {
                    iter->second->print_help();
                }
                return true;
            }
        }

        for (int ac = 1; ac < argc - 1; ++ac) {
            if (process_pair(argv[ac], argv[ac + 1]))
                ++ac;
        }

        return false;
    }

    /// \brief Process the options
    bool process (int argc, char **argv)
    {
        const char **cargv = new const char *[argc];
        for (int i = 0; i != argc; ++i)
            cargv[i] = argv[i];

        return process(argc, cargv);
    }

    /// \brief Count the number of occurence of an option on the command line
    /// given its name
    std::size_t count (const std::string &name) const
    {return option_cnt_.find("--" + name)->second;}

    private :

    std::map<std::string, ProgramOptionBase *> option_ptr_;
    std::map<std::string, std::size_t> option_cnt_;

    bool process_pair (const std::string &oname, const std::string &sval)
    {
        std::map<std::string, ProgramOptionBase *>::iterator iter =
            option_ptr_.find(oname);

        if (iter == option_ptr_.end())
            return false;

        if (!iter->second->set(sval))
            return false;

        ++option_cnt_[oname];
        return true;
    }
};

} // namespace vsmc

#endif // VSMC_UTILITY_PROGRAM_OPTION_HPP
<|endoftext|>


<commit_before>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.
 */

TEST(PackedFunc, Basic) {
  using namespace tvm;
  using namespace tvm::tir;
  using namespace tvm::runtime;
  int x = 0;
  void* handle = &x;
  DLTensor a;

  Var v = PackedFunc([&](TVMArgs args, TVMRetValue* rv) {
    ICHECK(args.num_args == 3);
    ICHECK(args.values[0].v_float64 == 1.0);
    ICHECK(args.type_codes[0] == kDLFloat);
    ICHECK(args.values[1].v_handle == &a);
    ICHECK(args.type_codes[1] == kTVMDLTensorHandle);
    ICHECK(args.values[2].v_handle == &x);
    ICHECK(args.type_codes[2] == kTVMOpaqueHandle);
    *rv = Var("a");
  })(1.0, &a, handle);
  ICHECK(v->name_hint == "a");
}

TEST(PackedFunc, Node) {
  using namespace tvm;
  using namespace tvm::tir;
  using namespace tvm::runtime;
  Var x;
  Var t = PackedFunc([&](TVMArgs args, TVMRetValue* rv) {
    ICHECK(args.num_args == 1);
    ICHECK(args[0].IsObjectRef<ObjectRef>());
    Var b = args[0];
    ICHECK(x.same_as(b));
    *rv = b;
  })(x);
  ICHECK(t.same_as(x));
}

TEST(PackedFunc, NDArray) {
  using namespace tvm;
  using namespace tvm::runtime;
  auto x = NDArray::Empty({}, String2DLDataType("float32"), Device{kDLCPU, 0});
  reinterpret_cast<float*>(x->data)[0] = 10.0f;
  ICHECK(x.use_count() == 1);

  PackedFunc forward([&](TVMArgs args, TVMRetValue* rv) { *rv = args[0]; });

  NDArray ret = PackedFunc([&](TVMArgs args, TVMRetValue* rv) {
    NDArray y = args[0];
    DLTensor* ptr = args[0];
    ICHECK(ptr == x.operator->());
    ICHECK(x.same_as(y));
    ICHECK(x.use_count() == 2);
    *rv = forward(y);
  })(x);
  ICHECK(ret.use_count() == 2);
  ICHECK(ret.same_as(x));
}

TEST(PackedFunc, str) {
  using namespace tvm;
  using namespace tvm::runtime;
  PackedFunc([&](TVMArgs args, TVMRetValue* rv) {
    ICHECK(args.num_args == 1);
    std::string x = args[0];
    ICHECK(x == "hello");
    String y = args[0];
    ICHECK(y == "hello");
    *rv = x;
  })("hello");

  PackedFunc([&](TVMArgs args, TVMRetValue* rv) {
    ICHECK(args.num_args == 1);
    runtime::String s = args[0];
    ICHECK(s == "hello");
  })(runtime::String("hello"));
}

TEST(PackedFunc, func) {
  using namespace tvm;
  using namespace tvm::runtime;
  PackedFunc addone([&](TVMArgs args, TVMRetValue* rv) { *rv = args[0].operator int() + 1; });
  // function as arguments
  int r0 = PackedFunc([](TVMArgs args, TVMRetValue* rv) {
    PackedFunc f = args[0];
    // TVMArgValue -> Arguments as function
    *rv = f(args[1]).operator int();
  })(addone, 1);
  ICHECK_EQ(r0, 2);

  int r1 = PackedFunc([](TVMArgs args, TVMRetValue* rv) {
    // TVMArgValue -> TVMRetValue
    *rv = args[1];
  })(2, 100);
  ICHECK_EQ(r1, 100);

  int r2 = PackedFunc([&](TVMArgs args, TVMRetValue* rv) {
    // re-assignment
    *rv = args[0];
    // TVMRetValue -> Function argument
    *rv = addone(args[0].operator PackedFunc()(args[1], 1));
  })(addone, 100);
  ICHECK_EQ(r2, 102);
}

TEST(PackedFunc, Expr) {
  using namespace tvm;
  using namespace tvm::runtime;
  // automatic conversion of int to expr
  PackedFunc addone([](TVMArgs args, TVMRetValue* rv) {
    PrimExpr x = args[0];
    *rv = x.as<tvm::tir::IntImmNode>()->value + 1;
  });
  int r0 = PackedFunc([](TVMArgs args, TVMRetValue* rv) {
    PackedFunc f = args[0];
    // TVMArgValue -> Arguments as function
    *rv = f(args[1]).operator int();
  })(addone, 1);
  ICHECK_EQ(r0, 2);
}

TEST(PackedFunc, Type) {
  using namespace tvm;
  using namespace tvm::runtime;
  auto get_type = PackedFunc([](TVMArgs args, TVMRetValue* rv) {
    DataType x = args[0];
    *rv = x;
  });
  auto get_type2 = PackedFunc([](TVMArgs args, TVMRetValue* rv) { *rv = args[0]; });
  ICHECK(get_type("int32").operator DataType() == DataType::Int(32));
  ICHECK(get_type("float").operator DataType() == DataType::Float(32));
  ICHECK(get_type2("float32x2").operator DataType() == DataType::Float(32, 2));
}

TEST(TypedPackedFunc, HighOrder) {
  using namespace tvm;
  using namespace tvm::runtime;
  using Int1Func = TypedPackedFunc<int(int)>;
  using Int2Func = TypedPackedFunc<int(int, int)>;
  using BindFunc = TypedPackedFunc<Int1Func(Int2Func, int value)>;
  BindFunc ftyped;
  ftyped = [](Int2Func f1, int value) -> Int1Func {
    auto binded = [f1, value](int x) { return f1(value, x); };
    Int1Func x(binded);
    return x;
  };
  auto add = [](int x, int y) { return x + y; };
  ICHECK_EQ(ftyped(Int2Func(add), 1)(2), 3);
  PackedFunc f = ftyped(Int2Func(add), 1);
  ICHECK_EQ(f(3).operator int(), 4);
  // call the type erased version.
  Int1Func f1 = ftyped.packed()(Int2Func(add), 1);
  ICHECK_EQ(f1(3), 4);
}

TEST(TypedPackedFunc, Deduce) {
  using namespace tvm::runtime;
  using tvm::runtime::detail::function_signature;

  TypedPackedFunc<int(float)> x;
  auto f = [](int x) -> int { return x + 1; };
  std::function<void(float)> y;

  static_assert(std::is_same<function_signature<decltype(x)>::FType, int(float)>::value,
                "invariant1");
  static_assert(std::is_same<function_signature<decltype(f)>::FType, int(int)>::value,
                "invariant2");
  static_assert(std::is_same<function_signature<decltype(y)>::FType, void(float)>::value,
                "invariant3");
}

TEST(PackedFunc, ObjectConversion) {
  using namespace tvm;
  using namespace tvm::tir;
  using namespace tvm::runtime;
  TVMRetValue rv;
  auto x = NDArray::Empty({}, String2DLDataType("float32"), Device{kDLCPU, 0});
  // assign null
  rv = ObjectRef();
  ICHECK_EQ(rv.type_code(), kTVMNullptr);

  // Can assign NDArray to ret type
  rv = x;
  ICHECK_EQ(rv.type_code(), kTVMNDArrayHandle);
  // Even if we assign base type it still shows as NDArray
  rv = ObjectRef(x);
  ICHECK_EQ(rv.type_code(), kTVMNDArrayHandle);
  // Check convert back
  ICHECK(rv.operator NDArray().same_as(x));
  ICHECK(rv.operator ObjectRef().same_as(x));
  ICHECK(!rv.IsObjectRef<PrimExpr>());

  auto pf1 = PackedFunc([&](TVMArgs args, TVMRetValue* rv) {
    ICHECK_EQ(args[0].type_code(), kTVMNDArrayHandle);
    ICHECK(args[0].operator NDArray().same_as(x));
    ICHECK(args[0].operator ObjectRef().same_as(x));
    ICHECK(args[1].operator ObjectRef().get() == nullptr);
    ICHECK(args[1].operator NDArray().get() == nullptr);
    ICHECK(args[1].operator Module().get() == nullptr);
    ICHECK(args[1].operator Array<NDArray>().get() == nullptr);
    ICHECK(!args[0].IsObjectRef<PrimExpr>());
  });
  pf1(x, ObjectRef());
  pf1(ObjectRef(x), NDArray());

  // testcases for modules
  auto* pf = tvm::runtime::Registry::Get("runtime.SourceModuleCreate");
  ICHECK(pf != nullptr);
  Module m = (*pf)("", "xyz");
  rv = m;
  ICHECK_EQ(rv.type_code(), kTVMModuleHandle);
  // Even if we assign base type it still shows as NDArray
  rv = ObjectRef(m);
  ICHECK_EQ(rv.type_code(), kTVMModuleHandle);
  // Check convert back
  ICHECK(rv.operator Module().same_as(m));
  ICHECK(rv.operator ObjectRef().same_as(m));
  ICHECK(!rv.IsObjectRef<NDArray>());

  auto pf2 = PackedFunc([&](TVMArgs args, TVMRetValue* rv) {
    ICHECK_EQ(args[0].type_code(), kTVMModuleHandle);
    ICHECK(args[0].operator Module().same_as(m));
    ICHECK(args[0].operator ObjectRef().same_as(m));
    ICHECK(args[1].operator ObjectRef().get() == nullptr);
    ICHECK(args[1].operator NDArray().get() == nullptr);
    ICHECK(args[1].operator Module().get() == nullptr);
    ICHECK(!args[0].IsObjectRef<PrimExpr>());
  });
  pf2(m, ObjectRef());
  pf2(ObjectRef(m), Module());
}

TEST(TypedPackedFunc, RValue) {
  using namespace tvm;
  using namespace tvm::runtime;
  {
    auto inspect = [](TVMArgs args, TVMRetValue* rv) {
      for (int i = 0; i < args.size(); ++i) {
        ICHECK_EQ(args[0].type_code(), kTVMObjectRValueRefArg);
      }
    };
    PackedFunc finspect(inspect);
    finspect(tir::Var("x"));
  }
  {
    auto f = [](tir::Var x, bool move) {
      if (move) {
        ICHECK(x.unique());
      } else {
        ICHECK(!x.unique());
      }
      ICHECK(x->name_hint == "x");
      return x;
    };
    TypedPackedFunc<tir::Var(tir::Var, bool)> tf(f);

    tir::Var var("x");
    ICHECK(var.unique());
    tf(var, false);
    // move the result to the function.
    tir::Var ret = tf(std::move(var), true);
    ICHECK(!var.defined());
  }

  {
    // pass child class.
    auto f = [](PrimExpr x, bool move) {
      if (move) {
        ICHECK(x.unique());
      } else {
        ICHECK(!x.unique());
      }
      return x;
    };
    TypedPackedFunc<PrimExpr(PrimExpr, bool)> tf(f);

    tir::Var var("x");
    ICHECK(var.unique());
    tf(var, false);
    tf(std::move(var), true);
    // auto conversion.
    tf(1, true);
  }
}

int main(int argc, char** argv) {
  testing::InitGoogleTest(&argc, argv);
  testing::FLAGS_gtest_death_test_style = "threadsafe";
  return RUN_ALL_TESTS();
}
<commit_msg>Remove duplicated PackedFunc C++ test (#8812)<commit_after><|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: ZipPackageFolderEnumeration.cxx,v $
 *
 *  $Revision: 1.9 $
 *
 *  last change: $Author: mtg $ $Date: 2001-11-15 20:30:34 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  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
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): Martin Gallwey (gallwey@sun.com)
 *
 *
 ************************************************************************/
#ifndef _ZIP_PACKAGE_FOLDER_ENUMERATION_HXX
#include <ZipPackageFolderEnumeration.hxx>
#endif
#ifndef _CONTENT_INFO_HXX_
#include <ContentInfo.hxx>
#endif

using namespace com::sun::star;
using rtl::OUString;

ZipPackageFolderEnumeration::ZipPackageFolderEnumeration ( ContentHash &rInput)
: rContents (rInput)
, aIterator (rInput.begin())
{
}

ZipPackageFolderEnumeration::~ZipPackageFolderEnumeration( void )
{
}

sal_Bool SAL_CALL ZipPackageFolderEnumeration::hasMoreElements(  )
        throw(uno::RuntimeException)
{
    return (aIterator != rContents.end() );
}
uno::Any SAL_CALL ZipPackageFolderEnumeration::nextElement(  )
        throw(container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException)
{
    uno::Any aAny;
    if (aIterator == rContents.end() )
        throw container::NoSuchElementException();
    aAny <<= (*aIterator).second->xTunnel;
    aIterator++;
    return aAny;
}

OUString ZipPackageFolderEnumeration::getImplementationName()
    throw (uno::RuntimeException)
{
    return OUString ( RTL_CONSTASCII_USTRINGPARAM ( "ZipPackageFolderEnumeration" ) );
}

uno::Sequence< OUString > ZipPackageFolderEnumeration::getSupportedServiceNames()
    throw (uno::RuntimeException)
{
    uno::Sequence< OUString > aNames(1);
    aNames[0] = OUString( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.packages.PackageFolderEnumeration" ) );
    return aNames;
}
sal_Bool SAL_CALL ZipPackageFolderEnumeration::supportsService( OUString const & rServiceName )
    throw (uno::RuntimeException)
{
    return rServiceName == getSupportedServiceNames()[0];
}
<commit_msg>INTEGRATION: CWS hr18 (1.9.214); FILE MERGED 2005/08/10 13:01:27 hr 1.9.214.1: #i53162#: ZipPackageFolderEnumeration c'tor: iterator is initialized from wrong container<commit_after>/*************************************************************************
 *
 *  $RCSfile: ZipPackageFolderEnumeration.cxx,v $
 *
 *  $Revision: 1.10 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-05 09:08:37 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  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
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): Martin Gallwey (gallwey@sun.com)
 *
 *
 ************************************************************************/
#ifndef _ZIP_PACKAGE_FOLDER_ENUMERATION_HXX
#include <ZipPackageFolderEnumeration.hxx>
#endif
#ifndef _CONTENT_INFO_HXX_
#include <ContentInfo.hxx>
#endif

using namespace com::sun::star;
using rtl::OUString;

ZipPackageFolderEnumeration::ZipPackageFolderEnumeration ( ContentHash &rInput)
: rContents (rInput)
, aIterator (rContents.begin())
{
}

ZipPackageFolderEnumeration::~ZipPackageFolderEnumeration( void )
{
}

sal_Bool SAL_CALL ZipPackageFolderEnumeration::hasMoreElements(  )
        throw(uno::RuntimeException)
{
    return (aIterator != rContents.end() );
}
uno::Any SAL_CALL ZipPackageFolderEnumeration::nextElement(  )
        throw(container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException)
{
    uno::Any aAny;
    if (aIterator == rContents.end() )
        throw container::NoSuchElementException();
    aAny <<= (*aIterator).second->xTunnel;
    aIterator++;
    return aAny;
}

OUString ZipPackageFolderEnumeration::getImplementationName()
    throw (uno::RuntimeException)
{
    return OUString ( RTL_CONSTASCII_USTRINGPARAM ( "ZipPackageFolderEnumeration" ) );
}

uno::Sequence< OUString > ZipPackageFolderEnumeration::getSupportedServiceNames()
    throw (uno::RuntimeException)
{
    uno::Sequence< OUString > aNames(1);
    aNames[0] = OUString( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.packages.PackageFolderEnumeration" ) );
    return aNames;
}
sal_Bool SAL_CALL ZipPackageFolderEnumeration::supportsService( OUString const & rServiceName )
    throw (uno::RuntimeException)
{
    return rServiceName == getSupportedServiceNames()[0];
}
<|endoftext|>


<commit_before>/*************************************************************************
 *                                                                       *
 * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith.       *
 * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
 *                                                                       *
 * This library is free software; you can redistribute it and/or         *
 * modify it under the terms of EITHER:                                  *
 *   (1) 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. The text of the GNU Lesser      *
 *       General Public License is included with this library in the     *
 *       file LICENSE.TXT.                                               *
 *   (2) The BSD-style license that is included with this library in     *
 *       the file LICENSE-BSD.TXT.                                       *
 *                                                                       *
 * 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 files    *
 * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
 *                                                                       *
 *************************************************************************/

// TriMesh code by Erwin de Vries.

#include <ode/collision.h>
#include <ode/matrix.h>
#include <ode/rotation.h>
#include <ode/odemath.h>
#include "collision_util.h"
#define TRIMESH_INTERNAL
#include "collision_trimesh_internal.h"

// Trimesh data
dxTriMeshData::dxTriMeshData(){
#ifndef dTRIMESH_ENABLED
  dUASSERT(g, "dTRIMESH_ENABLED is not defined. Trimesh geoms will not work");
#endif
}

dxTriMeshData::~dxTriMeshData(){
	//
}

void dxTriMeshData::Build(const void* Vertices, int VertexStide, int VertexCount, const void* Indices, int IndexCount, int TriStride, bool Single){
	Mesh.SetNbTriangles(IndexCount / 3);
	Mesh.SetNbVertices(VertexCount);
	Mesh.SetPointers((IndexedTriangle*)Indices, (Point*)Vertices);
	Mesh.SetStrides(TriStride, VertexStide);
	Mesh.Single = Single;

	// Build tree
	BuildSettings Settings;
	Settings.mRules = SPLIT_BEST_AXIS;

	OPCODECREATE TreeBuilder;
	TreeBuilder.mIMesh = &Mesh;

	TreeBuilder.mSettings = Settings;
	TreeBuilder.mNoLeaf = true;
	TreeBuilder.mQuantized = false;

	TreeBuilder.mKeepOriginal = false;
	TreeBuilder.mCanRemap = false;

	BVTree.Build(TreeBuilder);

	// compute model space AABB
	dVector3 AABBMax, AABBMin;
	AABBMax[0] = AABBMax[1] = AABBMax[2] = -dInfinity;
	AABBMin[0] = AABBMin[1] = AABBMin[2] = dInfinity;
	if( Single ) {
        const char* verts = (const char*)Vertices;
        for( int i = 0; i < VertexCount; ++i ) {
            const float* v = (const float*)verts;
            if( v[0] > AABBMax[0] ) AABBMax[0] = v[0];
            if( v[1] > AABBMax[1] ) AABBMax[1] = v[1];
            if( v[2] > AABBMax[2] ) AABBMax[2] = v[2];
            if( v[0] < AABBMin[0] ) AABBMin[0] = v[0];
            if( v[1] < AABBMin[1] ) AABBMin[1] = v[1];
            if( v[2] < AABBMin[2] ) AABBMin[2] = v[2];
            verts += VertexStide;
        }
    } else {
        const char* verts = (const char*)Vertices;
        for( int i = 0; i < VertexCount; ++i ) {
            const double* v = (const double*)verts;
            if( v[0] > AABBMax[0] ) AABBMax[0] = v[0];
            if( v[1] > AABBMax[1] ) AABBMax[1] = v[1];
            if( v[2] > AABBMax[2] ) AABBMax[2] = v[2];
            if( v[0] < AABBMin[0] ) AABBMin[0] = v[0];
            if( v[1] < AABBMin[1] ) AABBMin[1] = v[1];
            if( v[2] < AABBMin[2] ) AABBMin[2] = v[2];
            verts += VertexStide;
        }
    }
    AABBCenter[0] = (AABBMin[0] + AABBMax[0]) * REAL(0.5);
    AABBCenter[1] = (AABBMin[1] + AABBMax[1]) * REAL(0.5);
    AABBCenter[2] = (AABBMin[2] + AABBMax[2]) * REAL(0.5);
    AABBExtents[0] = AABBMax[0] - AABBCenter[0];
    AABBExtents[1] = AABBMax[1] - AABBCenter[1];
    AABBExtents[2] = AABBMax[2] - AABBCenter[2];
}

dTriMeshDataID dGeomTriMeshDataCreate(){
	return new dxTriMeshData();
}

void dGeomTriMeshDataDestroy(dTriMeshDataID g){
	delete g;
}

void dGeomTriMeshDataBuildSingle(dTriMeshDataID g, const void* Vertices, int VertexStride, int VertexCount,
								 const void* Indices, int IndexCount, int TriStride){
	dUASSERT(g, "argument not trimesh data");

	g->Build(Vertices, VertexStride, VertexCount, Indices, IndexCount, TriStride, true);
}

void dGeomTriMeshDataBuildDouble(dTriMeshDataID g, const void* Vertices, int VertexStride, int VertexCount,
								 const void* Indices, int IndexCount, int TriStride){
	dUASSERT(g, "argument not trimesh data");

	g->Build(Vertices, VertexStride, VertexCount, Indices, IndexCount, TriStride, false);
}

void dGeomTriMeshDataBuildSimple(dTriMeshDataID g, const dReal* Vertices, int VertexCount,
								 const int* Indices, int IndexCount){
#ifdef dSINGLE
	dGeomTriMeshDataBuildSingle(g, Vertices, 4 * sizeof(dReal), VertexCount, Indices, IndexCount, 3 * sizeof(unsigned int));
#else
	dGeomTriMeshDataBuildDouble(g, Vertices, 4 * sizeof(dReal), VertexCount, Indices, IndexCount, 3 * sizeof(unsigned int));
#endif
}

// Trimesh
PlanesCollider dxTriMesh::_PlanesCollider;
SphereCollider dxTriMesh::_SphereCollider;
OBBCollider dxTriMesh::_OBBCollider;
RayCollider dxTriMesh::_RayCollider;
AABBTreeCollider dxTriMesh::_AABBTreeCollider;

CollisionFaces dxTriMesh::Faces;

dxTriMesh::dxTriMesh(dSpaceID Space, dTriMeshDataID Data) : dxGeom(Space, 1){
	type = dTriMeshClass;

	this->Data = Data;

	_RayCollider.SetDestination(&Faces);

	_PlanesCollider.SetTemporalCoherence(true);
	_SphereCollider.SetTemporalCoherence(true);
	_OBBCollider.SetTemporalCoherence(true);
	_AABBTreeCollider.SetTemporalCoherence(true);

	_SphereCollider.SetPrimitiveTests(false);
}

dxTriMesh::~dxTriMesh(){
	//
}

void dxTriMesh::ClearTCCache(){
  /* dxTriMesh::ClearTCCache uses dArray's setSize(0) to clear the caches -
     but the destructor isn't called when doing this, so we would leak.
     So, call the previous caches' containers' destructors by hand first. */
	int i, n;
	n = SphereTCCache.size();
	for( i = 0; i < n; ++i ) {
	  SphereTCCache[i].~SphereTC();
	}
	SphereTCCache.setSize(0);
	n = BoxTCCache.size();
	for( i = 0; i < n; ++i ) {
	  BoxTCCache[i].~BoxTC();
	}
	BoxTCCache.setSize(0);
}

int dxTriMesh::AABBTest(dxGeom* g, dReal aabb[6]){
	return 1;
}

void dxTriMesh::computeAABB(){
        const dxTriMeshData* d = Data;
        dVector3 c;
        dMULTIPLY0_331( c, R, d->AABBCenter );
        dReal xrange = dFabs(R[0] * Data->AABBExtents[0]) +
	  dFabs(R[1] * Data->AABBExtents[1]) + dFabs(R[2] *
						     Data->AABBExtents[2]);
        dReal yrange = dFabs(R[4] * Data->AABBExtents[0]) +
	  dFabs(R[5] * Data->AABBExtents[1]) + dFabs(R[6] *
						     Data->AABBExtents[2]);
        dReal zrange = dFabs(R[8] * Data->AABBExtents[0]) +
	  dFabs(R[9] * Data->AABBExtents[1]) + dFabs(R[10] *
						     Data->AABBExtents[2]);
        aabb[0] = c[0] + pos[0] - xrange;
        aabb[1] = c[0] + pos[0] + xrange;
        aabb[2] = c[1] + pos[1] - yrange;
        aabb[3] = c[1] + pos[1] + yrange;
        aabb[4] = c[2] + pos[2] - zrange;
        aabb[5] = c[2] + pos[2] + zrange;
}

dGeomID dCreateTriMesh(dSpaceID space, dTriMeshDataID Data, dTriCallback* Callback, dTriArrayCallback* ArrayCallback, dTriRayCallback* RayCallback){
	dxTriMesh* Geom = new dxTriMesh(space, Data);
	Geom->Callback = Callback;
	Geom->ArrayCallback = ArrayCallback;
	Geom->RayCallback = RayCallback;

	return Geom;
}

void dGeomTriMeshClearTC(dGeomID g){
	dUASSERT(g && g->type == dTriMeshClass, "argument not a trimesh");

	dxTriMesh* Geom = (dxTriMesh*)g;
	Geom->ClearTCCache();
}

// Getting data
void dGeomTriMeshGetTriangle(dGeomID g, int Index, dVector3* v0, dVector3* v1, dVector3* v2){
	dUASSERT(g && g->type == dTriMeshClass, "argument not a trimesh");

	dxTriMesh* Geom = (dxTriMesh*)g;

	const dVector3& Position = *(const dVector3*)dGeomGetPosition(g);
	const dMatrix3& Rotation = *(const dMatrix3*)dGeomGetRotation(g);

	dVector3 v[3];
	FetchTriangle(Geom, Index, Rotation, Position, v);

	if (v0){
		(*v0)[0] = v[0][0];
		(*v0)[1] = v[0][1];
		(*v0)[2] = v[0][2];
		(*v0)[3] = v[0][3];
	}
	if (v1){
		(*v1)[0] = v[1][0];
		(*v1)[1] = v[1][1];
		(*v1)[2] = v[1][2];
		(*v1)[3] = v[0][3];
	}
	if (v2){
		(*v2)[0] = v[2][0];
		(*v2)[1] = v[2][1];
		(*v2)[2] = v[2][2];
		(*v2)[3] = v[2][3];
	}
}

void dGeomTriMeshGetPoint(dGeomID g, int Index, dReal u, dReal v, dVector3 Out){
	dUASSERT(g && g->type == dTriMeshClass, "argument not a trimesh");

	dxTriMesh* Geom = (dxTriMesh*)g;

	const dVector3& Position = *(const dVector3*)dGeomGetPosition(g);
	const dMatrix3& Rotation = *(const dMatrix3*)dGeomGetRotation(g);

	dVector3 dv[3];
	FetchTriangle(Geom, Index, Rotation, Position, dv);

	GetPointFromBarycentric(dv, u, v, Out);
}
<commit_msg>patch from vadim macagon (vadim_mcagon@hotmail.com): 'Basically the order of the Position/Rotation arguments in a call to FetchTriangle is incorrect.'<commit_after>/*************************************************************************
 *                                                                       *
 * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith.       *
 * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
 *                                                                       *
 * This library is free software; you can redistribute it and/or         *
 * modify it under the terms of EITHER:                                  *
 *   (1) 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. The text of the GNU Lesser      *
 *       General Public License is included with this library in the     *
 *       file LICENSE.TXT.                                               *
 *   (2) The BSD-style license that is included with this library in     *
 *       the file LICENSE-BSD.TXT.                                       *
 *                                                                       *
 * 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 files    *
 * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
 *                                                                       *
 *************************************************************************/

// TriMesh code by Erwin de Vries.

#include <ode/collision.h>
#include <ode/matrix.h>
#include <ode/rotation.h>
#include <ode/odemath.h>
#include "collision_util.h"
#define TRIMESH_INTERNAL
#include "collision_trimesh_internal.h"

// Trimesh data
dxTriMeshData::dxTriMeshData(){
#ifndef dTRIMESH_ENABLED
  dUASSERT(g, "dTRIMESH_ENABLED is not defined. Trimesh geoms will not work");
#endif
}

dxTriMeshData::~dxTriMeshData(){
	//
}

void dxTriMeshData::Build(const void* Vertices, int VertexStide, int VertexCount, const void* Indices, int IndexCount, int TriStride, bool Single){
	Mesh.SetNbTriangles(IndexCount / 3);
	Mesh.SetNbVertices(VertexCount);
	Mesh.SetPointers((IndexedTriangle*)Indices, (Point*)Vertices);
	Mesh.SetStrides(TriStride, VertexStide);
	Mesh.Single = Single;

	// Build tree
	BuildSettings Settings;
	Settings.mRules = SPLIT_BEST_AXIS;

	OPCODECREATE TreeBuilder;
	TreeBuilder.mIMesh = &Mesh;

	TreeBuilder.mSettings = Settings;
	TreeBuilder.mNoLeaf = true;
	TreeBuilder.mQuantized = false;

	TreeBuilder.mKeepOriginal = false;
	TreeBuilder.mCanRemap = false;

	BVTree.Build(TreeBuilder);

	// compute model space AABB
	dVector3 AABBMax, AABBMin;
	AABBMax[0] = AABBMax[1] = AABBMax[2] = -dInfinity;
	AABBMin[0] = AABBMin[1] = AABBMin[2] = dInfinity;
	if( Single ) {
        const char* verts = (const char*)Vertices;
        for( int i = 0; i < VertexCount; ++i ) {
            const float* v = (const float*)verts;
            if( v[0] > AABBMax[0] ) AABBMax[0] = v[0];
            if( v[1] > AABBMax[1] ) AABBMax[1] = v[1];
            if( v[2] > AABBMax[2] ) AABBMax[2] = v[2];
            if( v[0] < AABBMin[0] ) AABBMin[0] = v[0];
            if( v[1] < AABBMin[1] ) AABBMin[1] = v[1];
            if( v[2] < AABBMin[2] ) AABBMin[2] = v[2];
            verts += VertexStide;
        }
    } else {
        const char* verts = (const char*)Vertices;
        for( int i = 0; i < VertexCount; ++i ) {
            const double* v = (const double*)verts;
            if( v[0] > AABBMax[0] ) AABBMax[0] = v[0];
            if( v[1] > AABBMax[1] ) AABBMax[1] = v[1];
            if( v[2] > AABBMax[2] ) AABBMax[2] = v[2];
            if( v[0] < AABBMin[0] ) AABBMin[0] = v[0];
            if( v[1] < AABBMin[1] ) AABBMin[1] = v[1];
            if( v[2] < AABBMin[2] ) AABBMin[2] = v[2];
            verts += VertexStide;
        }
    }
    AABBCenter[0] = (AABBMin[0] + AABBMax[0]) * REAL(0.5);
    AABBCenter[1] = (AABBMin[1] + AABBMax[1]) * REAL(0.5);
    AABBCenter[2] = (AABBMin[2] + AABBMax[2]) * REAL(0.5);
    AABBExtents[0] = AABBMax[0] - AABBCenter[0];
    AABBExtents[1] = AABBMax[1] - AABBCenter[1];
    AABBExtents[2] = AABBMax[2] - AABBCenter[2];
}

dTriMeshDataID dGeomTriMeshDataCreate(){
	return new dxTriMeshData();
}

void dGeomTriMeshDataDestroy(dTriMeshDataID g){
	delete g;
}

void dGeomTriMeshDataBuildSingle(dTriMeshDataID g, const void* Vertices, int VertexStride, int VertexCount,
								 const void* Indices, int IndexCount, int TriStride){
	dUASSERT(g, "argument not trimesh data");

	g->Build(Vertices, VertexStride, VertexCount, Indices, IndexCount, TriStride, true);
}

void dGeomTriMeshDataBuildDouble(dTriMeshDataID g, const void* Vertices, int VertexStride, int VertexCount,
								 const void* Indices, int IndexCount, int TriStride){
	dUASSERT(g, "argument not trimesh data");

	g->Build(Vertices, VertexStride, VertexCount, Indices, IndexCount, TriStride, false);
}

void dGeomTriMeshDataBuildSimple(dTriMeshDataID g, const dReal* Vertices, int VertexCount,
								 const int* Indices, int IndexCount){
#ifdef dSINGLE
	dGeomTriMeshDataBuildSingle(g, Vertices, 4 * sizeof(dReal), VertexCount, Indices, IndexCount, 3 * sizeof(unsigned int));
#else
	dGeomTriMeshDataBuildDouble(g, Vertices, 4 * sizeof(dReal), VertexCount, Indices, IndexCount, 3 * sizeof(unsigned int));
#endif
}

// Trimesh
PlanesCollider dxTriMesh::_PlanesCollider;
SphereCollider dxTriMesh::_SphereCollider;
OBBCollider dxTriMesh::_OBBCollider;
RayCollider dxTriMesh::_RayCollider;
AABBTreeCollider dxTriMesh::_AABBTreeCollider;

CollisionFaces dxTriMesh::Faces;

dxTriMesh::dxTriMesh(dSpaceID Space, dTriMeshDataID Data) : dxGeom(Space, 1){
	type = dTriMeshClass;

	this->Data = Data;

	_RayCollider.SetDestination(&Faces);

	_PlanesCollider.SetTemporalCoherence(true);
	_SphereCollider.SetTemporalCoherence(true);
	_OBBCollider.SetTemporalCoherence(true);
	_AABBTreeCollider.SetTemporalCoherence(true);

	_SphereCollider.SetPrimitiveTests(false);
}

dxTriMesh::~dxTriMesh(){
	//
}

void dxTriMesh::ClearTCCache(){
  /* dxTriMesh::ClearTCCache uses dArray's setSize(0) to clear the caches -
     but the destructor isn't called when doing this, so we would leak.
     So, call the previous caches' containers' destructors by hand first. */
	int i, n;
	n = SphereTCCache.size();
	for( i = 0; i < n; ++i ) {
	  SphereTCCache[i].~SphereTC();
	}
	SphereTCCache.setSize(0);
	n = BoxTCCache.size();
	for( i = 0; i < n; ++i ) {
	  BoxTCCache[i].~BoxTC();
	}
	BoxTCCache.setSize(0);
}

int dxTriMesh::AABBTest(dxGeom* g, dReal aabb[6]){
	return 1;
}

void dxTriMesh::computeAABB(){
        const dxTriMeshData* d = Data;
        dVector3 c;
        dMULTIPLY0_331( c, R, d->AABBCenter );
        dReal xrange = dFabs(R[0] * Data->AABBExtents[0]) +
	  dFabs(R[1] * Data->AABBExtents[1]) + dFabs(R[2] *
						     Data->AABBExtents[2]);
        dReal yrange = dFabs(R[4] * Data->AABBExtents[0]) +
	  dFabs(R[5] * Data->AABBExtents[1]) + dFabs(R[6] *
						     Data->AABBExtents[2]);
        dReal zrange = dFabs(R[8] * Data->AABBExtents[0]) +
	  dFabs(R[9] * Data->AABBExtents[1]) + dFabs(R[10] *
						     Data->AABBExtents[2]);
        aabb[0] = c[0] + pos[0] - xrange;
        aabb[1] = c[0] + pos[0] + xrange;
        aabb[2] = c[1] + pos[1] - yrange;
        aabb[3] = c[1] + pos[1] + yrange;
        aabb[4] = c[2] + pos[2] - zrange;
        aabb[5] = c[2] + pos[2] + zrange;
}

dGeomID dCreateTriMesh(dSpaceID space, dTriMeshDataID Data, dTriCallback* Callback, dTriArrayCallback* ArrayCallback, dTriRayCallback* RayCallback){
	dxTriMesh* Geom = new dxTriMesh(space, Data);
	Geom->Callback = Callback;
	Geom->ArrayCallback = ArrayCallback;
	Geom->RayCallback = RayCallback;

	return Geom;
}

void dGeomTriMeshClearTC(dGeomID g){
	dUASSERT(g && g->type == dTriMeshClass, "argument not a trimesh");

	dxTriMesh* Geom = (dxTriMesh*)g;
	Geom->ClearTCCache();
}

// Getting data
void dGeomTriMeshGetTriangle(dGeomID g, int Index, dVector3* v0, dVector3* v1, dVector3* v2){
	dUASSERT(g && g->type == dTriMeshClass, "argument not a trimesh");

	dxTriMesh* Geom = (dxTriMesh*)g;

	const dVector3& Position = *(const dVector3*)dGeomGetPosition(g);
	const dMatrix3& Rotation = *(const dMatrix3*)dGeomGetRotation(g);

	dVector3 v[3];
	FetchTriangle(Geom, Index, Position, Rotation, v);

	if (v0){
		(*v0)[0] = v[0][0];
		(*v0)[1] = v[0][1];
		(*v0)[2] = v[0][2];
		(*v0)[3] = v[0][3];
	}
	if (v1){
		(*v1)[0] = v[1][0];
		(*v1)[1] = v[1][1];
		(*v1)[2] = v[1][2];
		(*v1)[3] = v[0][3];
	}
	if (v2){
		(*v2)[0] = v[2][0];
		(*v2)[1] = v[2][1];
		(*v2)[2] = v[2][2];
		(*v2)[3] = v[2][3];
	}
}

void dGeomTriMeshGetPoint(dGeomID g, int Index, dReal u, dReal v, dVector3 Out){
	dUASSERT(g && g->type == dTriMeshClass, "argument not a trimesh");

	dxTriMesh* Geom = (dxTriMesh*)g;

	const dVector3& Position = *(const dVector3*)dGeomGetPosition(g);
	const dMatrix3& Rotation = *(const dMatrix3*)dGeomGetRotation(g);

	dVector3 dv[3];
	FetchTriangle(Geom, Index, Position, Rotation, dv);

	GetPointFromBarycentric(dv, u, v, Out);
}
<|endoftext|>


<commit_before>/****************************************************************************
 * Copyright (c) 2012-2018 by the DataTransferKit authors                   *
 * All rights reserved.                                                     *
 *                                                                          *
 * This file is part of the DataTransferKit library. DataTransferKit is     *
 * distributed under a BSD 3-clause license. For the licensing terms see    *
 * the LICENSE file in the top-level directory.                             *
 *                                                                          *
 * SPDX-License-Identifier: BSD-3-Clause                                    *
 ****************************************************************************/

#include <DTK_DetailsDistributedSearchTreeImpl.hpp> // sendAcrossNetwork
#include <DTK_DetailsDistributor.hpp>
#include <DTK_DetailsNearestNeighborOperatorImpl.hpp> // fetch

#include <Teuchos_UnitTestHarness.hpp>

template <
    typename View,
    typename std::enable_if<
        std::is_same<
            typename View::traits::memory_space,
            typename View::traits::host_mirror_space::memory_space>::value,
        int>::type = 0>
Teuchos::ArrayView<typename View::const_value_type> toArray( View const &v )
{
    return Teuchos::ArrayView<typename View::const_value_type>( v.data(),
                                                                v.size() );
}

template <
    typename View,
    typename std::enable_if<
        !std::is_same<
            typename View::traits::memory_space,
            typename View::traits::host_mirror_space::memory_space>::value,
        int>::type = 0>
Teuchos::Array<typename View::non_const_value_type> toArray( View const &v )
{
    auto v_h = Kokkos::create_mirror_view( v );
    Kokkos::deep_copy( v_h, v );

    return Teuchos::Array<typename View::non_const_value_type>(
        Teuchos::ArrayView<typename View::const_value_type>( v_h.data(),
                                                             v_h.size() ) );
}

// NOTE Shameless hack to get DeviceType from test driver because I don't want
// to deduce it
template <typename DeviceType>
struct Helper
{
    template <typename View1, typename View2>
    static void checkSendAcrossNetwork( MPI_Comm comm, View1 const &ranks,
                                        View2 const &v_exp, View2 const &v_ref,
                                        bool &success,
                                        Teuchos::FancyOStream &out )
    {
        DataTransferKit::Details::Distributor distributor( comm );
        distributor.createFromSends( ranks );

        // NOTE here we assume that the reference solution is sized properly
        auto v_imp =
            Kokkos::create_mirror( typename View2::memory_space(), v_ref );

        DataTransferKit::Details::DistributedSearchTreeImpl<
            DeviceType>::sendAcrossNetwork( distributor, v_exp, v_imp );

        // FIXME not sure why I need that guy but I do get a bus error when it
        // is not here...
        Kokkos::fence();

        TEST_COMPARE_ARRAYS( toArray( v_imp ), toArray( v_ref ) );
    }

    template <typename View1, typename View2>
    static void checkFetch( MPI_Comm comm, View1 const &ranks,
                            View1 const &indices, View2 const &v_exp,
                            View2 const &v_ref, bool &success,
                            Teuchos::FancyOStream &out )
    {
        auto v_imp = DataTransferKit::Details::NearestNeighborOperatorImpl<
            DeviceType>::fetch( comm, ranks, indices, v_exp );

        TEST_COMPARE_ARRAYS( toArray( v_imp ), toArray( v_ref ) );
    }
};

TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( DetailsDistributedSearchTreeImpl,
                                   send_across_network, DeviceType )
{
    using ExecutionSpace = typename DeviceType::execution_space;

    MPI_Comm comm = MPI_COMM_WORLD;
    int comm_rank;
    MPI_Comm_rank( comm, &comm_rank );
    int comm_size;
    MPI_Comm_size( comm, &comm_size );

    int const DIM = 3;

    // send 1 packet to rank k
    // receive comm_size packets
    Kokkos::View<int **, DeviceType> u_exp( "u_exp", comm_size, DIM );
    Kokkos::parallel_for( Kokkos::RangePolicy<ExecutionSpace>( 0, comm_size ),
                          KOKKOS_LAMBDA( int i ) {
                              for ( int j = 0; j < DIM; ++j )
                                  u_exp( i, j ) = i + j * comm_rank;
                          } );
    Kokkos::fence();

    Kokkos::View<int *, DeviceType> ranks_u( "", comm_size );
    DataTransferKit::iota( ranks_u, 0 );

    Kokkos::View<int **, DeviceType> u_ref( "u_ref", comm_size, DIM );
    Kokkos::parallel_for( Kokkos::RangePolicy<ExecutionSpace>( 0, comm_size ),
                          KOKKOS_LAMBDA( int i ) {
                              for ( int j = 0; j < DIM; ++j )
                                  u_ref( i, j ) = comm_rank + i * j;
                          } );
    Kokkos::fence();

    Helper<DeviceType>::checkSendAcrossNetwork( comm, ranks_u, u_exp, u_ref,
                                                success, out );

    // send k packets to rank k
    // receive k*comm_size packets
    Kokkos::View<int *, DeviceType> tn( "tn", comm_size + 1 );
    Kokkos::parallel_for(
        Kokkos::RangePolicy<ExecutionSpace>( 0, comm_size + 1 ),
        KOKKOS_LAMBDA( int i ) { tn( i ) = ( i * ( i - 1 ) ) / 2; } );
    Kokkos::fence();

    Kokkos::View<int **, DeviceType> v_exp(
        "v_exp", DataTransferKit::lastElement( tn ), DIM );
    Kokkos::parallel_for( Kokkos::RangePolicy<ExecutionSpace>( 0, comm_size ),
                          KOKKOS_LAMBDA( int i ) {
                              for ( int j = tn( i ); j < tn( i + 1 ); ++j )
                                  for ( int k = 0; k < DIM; ++k )
                                      v_exp( j, k ) = i * k;
                          } );
    Kokkos::fence();

    Kokkos::View<int *, DeviceType> ranks_v(
        "", DataTransferKit::lastElement( tn ) );
    Kokkos::parallel_for( Kokkos::RangePolicy<ExecutionSpace>( 0, comm_size ),
                          KOKKOS_LAMBDA( int i ) {
                              for ( int j = tn( i ); j < tn( i + 1 ); ++j )
                                  ranks_v( j ) = i;
                          } );
    Kokkos::fence();

    Kokkos::View<int **, DeviceType> v_ref( "v_ref", comm_size * comm_rank,
                                            DIM );
    Kokkos::parallel_for(
        Kokkos::RangePolicy<ExecutionSpace>( 0, comm_size * comm_rank ),
        KOKKOS_LAMBDA( int i ) {
            for ( int j = 0; j < DIM; ++j )
                v_ref( i, j ) = j * comm_rank;
        } );
    Kokkos::fence();

    Helper<DeviceType>::checkSendAcrossNetwork( comm, ranks_v, v_exp, v_ref,
                                                success, out );
}

TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( DetailsNearestNeighborOperatorImpl, fetch,
                                   DeviceType )
{
    using ExecutionSpace = typename DeviceType::execution_space;

    MPI_Comm comm = MPI_COMM_WORLD;
    int comm_rank;
    MPI_Comm_rank( comm, &comm_rank );
    int comm_size;
    MPI_Comm_size( comm, &comm_size );

    // make communicaton plan
    Kokkos::View<int *, DeviceType> indices( "indices", comm_size );
    Kokkos::View<int *, DeviceType> ranks( "ranks", comm_size );
    Kokkos::parallel_for( Kokkos::RangePolicy<ExecutionSpace>( 0, comm_size ),
                          KOKKOS_LAMBDA( int i ) {
                              indices( i ) = ( comm_rank + i ) % comm_size;
                              ranks( i ) = comm_size - 1 - comm_rank;
                          } );
    Kokkos::fence();

    // v(i) <-- k*comm_size+i (index i, rank k)
    Kokkos::View<int *, DeviceType> v_exp( "v", comm_size );
    DataTransferKit::iota( v_exp, comm_rank * comm_size );

    Kokkos::View<int *, DeviceType> v_ref( "v_ref", comm_size );
    Kokkos::parallel_for( Kokkos::RangePolicy<ExecutionSpace>( 0, comm_size ),
                          KOKKOS_LAMBDA( int i ) {
                              v_ref( i ) =
                                  ranks( i ) * comm_size + indices( i );
                          } );
    Kokkos::fence();

    Helper<DeviceType>::checkFetch( comm, ranks, indices, v_exp, v_ref, success,
                                    out );

    // w(i, j) <-- k*comm_size*DIM+i+j*comm_size (index i, index j, rank k)
    int const DIM = 2;
    Kokkos::View<int **, DeviceType> w_exp( "w", comm_size, DIM );
    for ( int i = 0; i < DIM; ++i )
        DataTransferKit::iota( Kokkos::subview( w_exp, Kokkos::ALL, i ),
                               i * comm_size + comm_rank * comm_size * DIM );

    Kokkos::View<int **, DeviceType> w_ref( "w_ref", comm_size, DIM );
    Kokkos::parallel_for( Kokkos::RangePolicy<ExecutionSpace>( 0, comm_size ),
                          KOKKOS_LAMBDA( int i ) {
                              for ( int j = 0; j < DIM; ++j )
                                  w_ref( i, j ) = ranks( i ) * comm_size * DIM +
                                                  indices( i ) + j * comm_size;
                          } );
    Kokkos::fence();

    Helper<DeviceType>::checkFetch( comm, ranks, indices, w_exp, w_ref, success,
                                    out );
}

// Include the test macros.
#include "DataTransferKit_ETIHelperMacros.h"

// Create the test group
#define UNIT_TEST_GROUP( NODE )                                                \
    using DeviceType##NODE = typename NODE::device_type;                       \
    TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( DetailsDistributedSearchTreeImpl,    \
                                          send_across_network,                 \
                                          DeviceType##NODE )                   \
    TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( DetailsNearestNeighborOperatorImpl,  \
                                          fetch, DeviceType##NODE )

// Demangle the types
DTK_ETI_MANGLING_TYPEDEFS()

// Instantiate the tests
DTK_INSTANTIATE_N( UNIT_TEST_GROUP )
<commit_msg>Add missing include in tstDetailsCommunicationHelpers.cpp<commit_after>/****************************************************************************
 * Copyright (c) 2012-2018 by the DataTransferKit authors                   *
 * All rights reserved.                                                     *
 *                                                                          *
 * This file is part of the DataTransferKit library. DataTransferKit is     *
 * distributed under a BSD 3-clause license. For the licensing terms see    *
 * the LICENSE file in the top-level directory.                             *
 *                                                                          *
 * SPDX-License-Identifier: BSD-3-Clause                                    *
 ****************************************************************************/

#include <DTK_DetailsDistributedSearchTreeImpl.hpp> // sendAcrossNetwork
#include <DTK_DetailsDistributor.hpp>
#include <DTK_DetailsNearestNeighborOperatorImpl.hpp> // fetch

#include <Teuchos_Array.hpp>
#include <Teuchos_UnitTestHarness.hpp>

template <
    typename View,
    typename std::enable_if<
        std::is_same<
            typename View::traits::memory_space,
            typename View::traits::host_mirror_space::memory_space>::value,
        int>::type = 0>
Teuchos::ArrayView<typename View::const_value_type> toArray( View const &v )
{
    return Teuchos::ArrayView<typename View::const_value_type>( v.data(),
                                                                v.size() );
}

template <
    typename View,
    typename std::enable_if<
        !std::is_same<
            typename View::traits::memory_space,
            typename View::traits::host_mirror_space::memory_space>::value,
        int>::type = 0>
Teuchos::Array<typename View::non_const_value_type> toArray( View const &v )
{
    auto v_h = Kokkos::create_mirror_view( v );
    Kokkos::deep_copy( v_h, v );

    return Teuchos::Array<typename View::non_const_value_type>(
        Teuchos::ArrayView<typename View::const_value_type>( v_h.data(),
                                                             v_h.size() ) );
}

// NOTE Shameless hack to get DeviceType from test driver because I don't want
// to deduce it
template <typename DeviceType>
struct Helper
{
    template <typename View1, typename View2>
    static void checkSendAcrossNetwork( MPI_Comm comm, View1 const &ranks,
                                        View2 const &v_exp, View2 const &v_ref,
                                        bool &success,
                                        Teuchos::FancyOStream &out )
    {
        DataTransferKit::Details::Distributor distributor( comm );
        distributor.createFromSends( ranks );

        // NOTE here we assume that the reference solution is sized properly
        auto v_imp =
            Kokkos::create_mirror( typename View2::memory_space(), v_ref );

        DataTransferKit::Details::DistributedSearchTreeImpl<
            DeviceType>::sendAcrossNetwork( distributor, v_exp, v_imp );

        // FIXME not sure why I need that guy but I do get a bus error when it
        // is not here...
        Kokkos::fence();

        TEST_COMPARE_ARRAYS( toArray( v_imp ), toArray( v_ref ) );
    }

    template <typename View1, typename View2>
    static void checkFetch( MPI_Comm comm, View1 const &ranks,
                            View1 const &indices, View2 const &v_exp,
                            View2 const &v_ref, bool &success,
                            Teuchos::FancyOStream &out )
    {
        auto v_imp = DataTransferKit::Details::NearestNeighborOperatorImpl<
            DeviceType>::fetch( comm, ranks, indices, v_exp );

        TEST_COMPARE_ARRAYS( toArray( v_imp ), toArray( v_ref ) );
    }
};

TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( DetailsDistributedSearchTreeImpl,
                                   send_across_network, DeviceType )
{
    using ExecutionSpace = typename DeviceType::execution_space;

    MPI_Comm comm = MPI_COMM_WORLD;
    int comm_rank;
    MPI_Comm_rank( comm, &comm_rank );
    int comm_size;
    MPI_Comm_size( comm, &comm_size );

    int const DIM = 3;

    // send 1 packet to rank k
    // receive comm_size packets
    Kokkos::View<int **, DeviceType> u_exp( "u_exp", comm_size, DIM );
    Kokkos::parallel_for( Kokkos::RangePolicy<ExecutionSpace>( 0, comm_size ),
                          KOKKOS_LAMBDA( int i ) {
                              for ( int j = 0; j < DIM; ++j )
                                  u_exp( i, j ) = i + j * comm_rank;
                          } );
    Kokkos::fence();

    Kokkos::View<int *, DeviceType> ranks_u( "", comm_size );
    DataTransferKit::iota( ranks_u, 0 );

    Kokkos::View<int **, DeviceType> u_ref( "u_ref", comm_size, DIM );
    Kokkos::parallel_for( Kokkos::RangePolicy<ExecutionSpace>( 0, comm_size ),
                          KOKKOS_LAMBDA( int i ) {
                              for ( int j = 0; j < DIM; ++j )
                                  u_ref( i, j ) = comm_rank + i * j;
                          } );
    Kokkos::fence();

    Helper<DeviceType>::checkSendAcrossNetwork( comm, ranks_u, u_exp, u_ref,
                                                success, out );

    // send k packets to rank k
    // receive k*comm_size packets
    Kokkos::View<int *, DeviceType> tn( "tn", comm_size + 1 );
    Kokkos::parallel_for(
        Kokkos::RangePolicy<ExecutionSpace>( 0, comm_size + 1 ),
        KOKKOS_LAMBDA( int i ) { tn( i ) = ( i * ( i - 1 ) ) / 2; } );
    Kokkos::fence();

    Kokkos::View<int **, DeviceType> v_exp(
        "v_exp", DataTransferKit::lastElement( tn ), DIM );
    Kokkos::parallel_for( Kokkos::RangePolicy<ExecutionSpace>( 0, comm_size ),
                          KOKKOS_LAMBDA( int i ) {
                              for ( int j = tn( i ); j < tn( i + 1 ); ++j )
                                  for ( int k = 0; k < DIM; ++k )
                                      v_exp( j, k ) = i * k;
                          } );
    Kokkos::fence();

    Kokkos::View<int *, DeviceType> ranks_v(
        "", DataTransferKit::lastElement( tn ) );
    Kokkos::parallel_for( Kokkos::RangePolicy<ExecutionSpace>( 0, comm_size ),
                          KOKKOS_LAMBDA( int i ) {
                              for ( int j = tn( i ); j < tn( i + 1 ); ++j )
                                  ranks_v( j ) = i;
                          } );
    Kokkos::fence();

    Kokkos::View<int **, DeviceType> v_ref( "v_ref", comm_size * comm_rank,
                                            DIM );
    Kokkos::parallel_for(
        Kokkos::RangePolicy<ExecutionSpace>( 0, comm_size * comm_rank ),
        KOKKOS_LAMBDA( int i ) {
            for ( int j = 0; j < DIM; ++j )
                v_ref( i, j ) = j * comm_rank;
        } );
    Kokkos::fence();

    Helper<DeviceType>::checkSendAcrossNetwork( comm, ranks_v, v_exp, v_ref,
                                                success, out );
}

TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( DetailsNearestNeighborOperatorImpl, fetch,
                                   DeviceType )
{
    using ExecutionSpace = typename DeviceType::execution_space;

    MPI_Comm comm = MPI_COMM_WORLD;
    int comm_rank;
    MPI_Comm_rank( comm, &comm_rank );
    int comm_size;
    MPI_Comm_size( comm, &comm_size );

    // make communicaton plan
    Kokkos::View<int *, DeviceType> indices( "indices", comm_size );
    Kokkos::View<int *, DeviceType> ranks( "ranks", comm_size );
    Kokkos::parallel_for( Kokkos::RangePolicy<ExecutionSpace>( 0, comm_size ),
                          KOKKOS_LAMBDA( int i ) {
                              indices( i ) = ( comm_rank + i ) % comm_size;
                              ranks( i ) = comm_size - 1 - comm_rank;
                          } );
    Kokkos::fence();

    // v(i) <-- k*comm_size+i (index i, rank k)
    Kokkos::View<int *, DeviceType> v_exp( "v", comm_size );
    DataTransferKit::iota( v_exp, comm_rank * comm_size );

    Kokkos::View<int *, DeviceType> v_ref( "v_ref", comm_size );
    Kokkos::parallel_for( Kokkos::RangePolicy<ExecutionSpace>( 0, comm_size ),
                          KOKKOS_LAMBDA( int i ) {
                              v_ref( i ) =
                                  ranks( i ) * comm_size + indices( i );
                          } );
    Kokkos::fence();

    Helper<DeviceType>::checkFetch( comm, ranks, indices, v_exp, v_ref, success,
                                    out );

    // w(i, j) <-- k*comm_size*DIM+i+j*comm_size (index i, index j, rank k)
    int const DIM = 2;
    Kokkos::View<int **, DeviceType> w_exp( "w", comm_size, DIM );
    for ( int i = 0; i < DIM; ++i )
        DataTransferKit::iota( Kokkos::subview( w_exp, Kokkos::ALL, i ),
                               i * comm_size + comm_rank * comm_size * DIM );

    Kokkos::View<int **, DeviceType> w_ref( "w_ref", comm_size, DIM );
    Kokkos::parallel_for( Kokkos::RangePolicy<ExecutionSpace>( 0, comm_size ),
                          KOKKOS_LAMBDA( int i ) {
                              for ( int j = 0; j < DIM; ++j )
                                  w_ref( i, j ) = ranks( i ) * comm_size * DIM +
                                                  indices( i ) + j * comm_size;
                          } );
    Kokkos::fence();

    Helper<DeviceType>::checkFetch( comm, ranks, indices, w_exp, w_ref, success,
                                    out );
}

// Include the test macros.
#include "DataTransferKit_ETIHelperMacros.h"

// Create the test group
#define UNIT_TEST_GROUP( NODE )                                                \
    using DeviceType##NODE = typename NODE::device_type;                       \
    TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( DetailsDistributedSearchTreeImpl,    \
                                          send_across_network,                 \
                                          DeviceType##NODE )                   \
    TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( DetailsNearestNeighborOperatorImpl,  \
                                          fetch, DeviceType##NODE )

// Demangle the types
DTK_ETI_MANGLING_TYPEDEFS()

// Instantiate the tests
DTK_INSTANTIATE_N( UNIT_TEST_GROUP )
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2003-2005 The Regents of The University of Michigan
 * 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 the copyright holders 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.
 *
 * Authors: Nathan Binkert
 */

#ifndef __ARCH_ALPHA_ARGUMENTS_HH__
#define __ARCH_ALPHA_ARGUMENTS_HH__

#include <assert.h>

#include "arch/alpha/vtophys.hh"
#include "base/refcnt.hh"
#include "sim/host.hh"

class ThreadContext;

namespace AlphaISA {

class Arguments
{
  protected:
    ThreadContext *tc;
    int number;
    uint64_t getArg(bool fp = false);

  protected:
    class Data : public RefCounted
    {
      public:
        Data(){}
        ~Data();

      private:
        std::list<char *> data;

      public:
        char *alloc(size_t size);
    };

    RefCountingPtr<Data> data;

  public:
    Arguments(ThreadContext *ctx, int n = 0)
        : tc(ctx), number(n), data(NULL)
        { assert(number >= 0); data = new Data;}
    Arguments(const Arguments &args)
        : tc(args.tc), number(args.number), data(args.data) {}
    ~Arguments() {}

    ThreadContext *getThreadContext() const { return tc; }

    const Arguments &operator=(const Arguments &args) {
        tc = args.tc;
        number = args.number;
        data = args.data;
        return *this;
    }

    Arguments &operator++() {
        ++number;
        assert(number >= 0);
        return *this;
    }

    Arguments operator++(int) {
        Arguments args = *this;
        ++number;
        assert(number >= 0);
        return args;
    }

    Arguments &operator--() {
        --number;
        assert(number >= 0);
        return *this;
    }

    Arguments operator--(int) {
        Arguments args = *this;
        --number;
        assert(number >= 0);
        return args;
    }

    const Arguments &operator+=(int index) {
        number += index;
        assert(number >= 0);
        return *this;
    }

    const Arguments &operator-=(int index) {
        number -= index;
        assert(number >= 0);
        return *this;
    }

    Arguments operator[](int index) {
        return Arguments(tc, index);
    }

    template <class T>
    operator T() {
        assert(sizeof(T) <= sizeof(uint64_t));
        T data = static_cast<T>(getArg());
        return data;
    }

    template <class T>
    operator T *() {
        T *buf = (T *)data->alloc(sizeof(T));
        CopyData(tc, buf, getArg(), sizeof(T));
        return buf;
    }

    operator char *() {
        char *buf = data->alloc(2048);
        CopyStringOut(tc, buf, getArg(), 2048);
        return buf;
    }
};

}; // namespace AlphaISA

#endif // __ARCH_ALPHA_ARGUMENTS_HH__
<commit_msg>#include needed for compile<commit_after>/*
 * Copyright (c) 2003-2005 The Regents of The University of Michigan
 * 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 the copyright holders 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.
 *
 * Authors: Nathan Binkert
 */

#ifndef __ARCH_ALPHA_ARGUMENTS_HH__
#define __ARCH_ALPHA_ARGUMENTS_HH__

#include <assert.h>

#include "arch/alpha/vtophys.hh"
#include "base/refcnt.hh"
#include "mem/vport.hh"
#include "sim/host.hh"

class ThreadContext;

namespace AlphaISA {

class Arguments
{
  protected:
    ThreadContext *tc;
    int number;
    uint64_t getArg(bool fp = false);

  protected:
    class Data : public RefCounted
    {
      public:
        Data(){}
        ~Data();

      private:
        std::list<char *> data;

      public:
        char *alloc(size_t size);
    };

    RefCountingPtr<Data> data;

  public:
    Arguments(ThreadContext *ctx, int n = 0)
        : tc(ctx), number(n), data(NULL)
        { assert(number >= 0); data = new Data;}
    Arguments(const Arguments &args)
        : tc(args.tc), number(args.number), data(args.data) {}
    ~Arguments() {}

    ThreadContext *getThreadContext() const { return tc; }

    const Arguments &operator=(const Arguments &args) {
        tc = args.tc;
        number = args.number;
        data = args.data;
        return *this;
    }

    Arguments &operator++() {
        ++number;
        assert(number >= 0);
        return *this;
    }

    Arguments operator++(int) {
        Arguments args = *this;
        ++number;
        assert(number >= 0);
        return args;
    }

    Arguments &operator--() {
        --number;
        assert(number >= 0);
        return *this;
    }

    Arguments operator--(int) {
        Arguments args = *this;
        --number;
        assert(number >= 0);
        return args;
    }

    const Arguments &operator+=(int index) {
        number += index;
        assert(number >= 0);
        return *this;
    }

    const Arguments &operator-=(int index) {
        number -= index;
        assert(number >= 0);
        return *this;
    }

    Arguments operator[](int index) {
        return Arguments(tc, index);
    }

    template <class T>
    operator T() {
        assert(sizeof(T) <= sizeof(uint64_t));
        T data = static_cast<T>(getArg());
        return data;
    }

    template <class T>
    operator T *() {
        T *buf = (T *)data->alloc(sizeof(T));
        CopyData(tc, buf, getArg(), sizeof(T));
        return buf;
    }

    operator char *() {
        char *buf = data->alloc(2048);
        CopyStringOut(tc, buf, getArg(), 2048);
        return buf;
    }
};

}; // namespace AlphaISA

#endif // __ARCH_ALPHA_ARGUMENTS_HH__
<|endoftext|>


<commit_before>#include"../header/CThreadPoolCommun.h"
#include<utility>	//move
#include"../../lib/header/thread/CThreadList.h"
#include"../../lib/header/thread/CThreadQueue.h"
#include"../header/CThreadPoolItem.h"
using namespace std;

namespace nThread
{
	void CThreadPoolCommunBase::detach_(){}

	void CThreadPoolCommunBase::finish_(){}

	void CThreadPoolCommunBase::join_(){}

	void CThreadPoolCommunBase::communPoolDetach()
	{
		detach_();
	}

	void CThreadPoolCommunBase::communPoolFinish()
	{
		finish_();
	}

	void CThreadPoolCommunBase::communPoolJoin()
	{
		join_();
	}

	CThreadPoolCommunBase::~CThreadPoolCommunBase(){}

	struct CThreadPoolCommun::Impl
	{
		CThreadPoolItem *item;
		CThreadList<CThreadPoolItem*> *join_anyList;	//or use deque
		CThreadQueue<CThreadPoolItem*> *waitingQue;
		Impl(CThreadPoolItem *,CThreadList<CThreadPoolItem*> *,CThreadQueue<CThreadPoolItem*> *);
		void destroy();
		inline void detach()
		{
			waitingQue->emplace(item);
		}
		inline void func_is_completed()	//notify CThreadPool::join_any
		{
			join_anyList->emplace_back(item);
		}
	};

	CThreadPoolCommun::Impl::Impl(CThreadPoolItem *item_,CThreadList<CThreadPoolItem*> *join_anyList_,CThreadQueue<CThreadPoolItem*> *waitingQue_)
		:item{item_},join_anyList{join_anyList_},waitingQue{waitingQue_}{}

	void CThreadPoolCommun::Impl::destroy()
	{
		join_anyList->remove_if([&](const CThreadPoolItem *val){return val->get_id()==item->get_id();});
		//if CThreadPool::join_any run first, this would not erase anything (it's ok)
		waitingQue->emplace(item);
	}

	CThreadPoolCommun::CThreadPoolCommun(CThreadPoolItem *item,CThreadList<CThreadPoolItem*> *join_anyList,CThreadQueue<CThreadPoolItem*> *waitingQue)
		:impl_{item,join_anyList,waitingQue}{}

	CThreadPoolCommun::CThreadPoolCommun(CThreadPoolCommun &&rVal) noexcept
		:impl_{move(rVal.impl_)}{}

	void CThreadPoolCommun::destroy()
	{
		impl_.get().destroy();
	}

	void CThreadPoolCommun::detach()
	{
		impl_.get().detach();
	}

	void CThreadPoolCommun::func_is_completed()
	{
		impl_.get().func_is_completed();
	}

	CThreadPoolCommun& CThreadPoolCommun::operator=(CThreadPoolCommun &&rVal) noexcept
	{
		impl_=move(rVal.impl_);
		return *this;
	}

	CThreadPoolCommun::~CThreadPoolCommun(){}
}<commit_msg>remove useless function<commit_after>#include"../header/CThreadPoolCommun.h"
#include<utility>	//move
#include"../../lib/header/thread/CThreadList.h"
#include"../../lib/header/thread/CThreadQueue.h"
#include"../header/CThreadPoolItem.h"
using namespace std;

namespace nThread
{
	CThreadPoolCommunBase::~CThreadPoolCommunBase(){}

	struct CThreadPoolCommun::Impl
	{
		CThreadPoolItem *item;
		CThreadList<CThreadPoolItem*> *join_anyList;	//or use deque
		CThreadQueue<CThreadPoolItem*> *waitingQue;
		Impl(CThreadPoolItem *,CThreadList<CThreadPoolItem*> *,CThreadQueue<CThreadPoolItem*> *);
		void destroy();
		inline void detach()
		{
			waitingQue->emplace(item);
		}
		inline void func_is_completed()	//notify CThreadPool::join_any
		{
			join_anyList->emplace_back(item);
		}
	};

	CThreadPoolCommun::Impl::Impl(CThreadPoolItem *item_,CThreadList<CThreadPoolItem*> *join_anyList_,CThreadQueue<CThreadPoolItem*> *waitingQue_)
		:item{item_},join_anyList{join_anyList_},waitingQue{waitingQue_}{}

	void CThreadPoolCommun::Impl::destroy()
	{
		join_anyList->remove_if([&](const CThreadPoolItem *val){return val->get_id()==item->get_id();});
		//if CThreadPool::join_any run first, this would not erase anything (it's ok)
		waitingQue->emplace(item);
	}

	CThreadPoolCommun::CThreadPoolCommun(CThreadPoolItem *item,CThreadList<CThreadPoolItem*> *join_anyList,CThreadQueue<CThreadPoolItem*> *waitingQue)
		:impl_{item,join_anyList,waitingQue}{}

	CThreadPoolCommun::CThreadPoolCommun(CThreadPoolCommun &&rVal) noexcept
		:impl_{move(rVal.impl_)}{}

	void CThreadPoolCommun::destroy()
	{
		impl_.get().destroy();
	}

	void CThreadPoolCommun::detach()
	{
		impl_.get().detach();
	}

	void CThreadPoolCommun::func_is_completed()
	{
		impl_.get().func_is_completed();
	}

	CThreadPoolCommun& CThreadPoolCommun::operator=(CThreadPoolCommun &&rVal) noexcept
	{
		impl_=move(rVal.impl_);
		return *this;
	}

	CThreadPoolCommun::~CThreadPoolCommun(){}
}<|endoftext|>