<commit_before>#pragma once

#include <string>
#include <vector>
#include <tuple>
#include <sstream>
#include <type_traits>
#include <functional>
#include <memory>
#include <unordered_map>

namespace argparse {

namespace detail {
    template <typename In, typename Out, bool pass = std::is_convertible<In, Out>::value>
    struct lexical_cast_t;

    template <typename In, typename Out>
    struct lexical_cast_t<In, Out, true> {
        static Out apply(In const& val) {
            return static_cast<Out>(val);
        }
    };

    template <typename In>
    struct lexical_cast_t<In, std::string, false> {
        static std::string apply(In const& val) {
            std::ostringstream osstr;
            osstr << val;
            return osstr.str();
        }
    };

    template <typename Out>
    struct lexical_cast_t<std::string, Out, false> {
        static Out apply(std::string const& val) {
            std::istringstream isstr(val);
            Out out;
            isstr >> out;
            return out;
        }
    };

    template <typename Out, std::size_t N>
    struct lexical_cast_t<char[N], Out, false> {
        static Out apply(char const (&val)[N]) {
            std::istringstream isstr(val);
            Out out;
            isstr >> out;
            return out;
        }
    };

    template <typename Out, std::size_t N>
    struct lexical_cast_t<char const[N], Out, false> {
        static Out apply(char const (&val)[N]) {
            std::istringstream isstr(val);
            Out out;
            isstr >> out;
            return out;
        }
    };
} // namespace detail;

template <typename Out, typename In>
inline Out lexical_cast(In const& val) {
    return detail::lexical_cast_t<In, Out>::apply(val);
}

//

struct argument_base {
   virtual void assign(std::string const& src) = 0;
   virtual void store_true() = 0;
   virtual bool with_value() const = 0;

   argument_base(std::string const& name, char short_name,
                 std::string const& help)
     : name_{name}, short_name_{short_name}, help_{help}
  {
  }

   std::string const& name() const { return name_; }
   char short_name() const { return short_name_; }

private:
   std::string name_;
   char short_name_;
   std::string help_;
};

template <typename T>
struct argument_with_value : public argument_base {
   using arg_type = T;

   argument_with_value(std::string const& name, char short_name,
                       std::string const& help)
      : argument_base{name, short_name, help}
   {
   }

   void assign(std::string const& src) override {
      val_.reset(new T(lexical_cast<T>(src)));
   }

   void store_true() override { /* do nothing. */ }
   bool with_value() const override { return true; }

private:
   std::unique_ptr<T> val_;
};

struct argument_flag : public argument_base {
   using arg_type = bool;

   argument_flag(std::string const& name, char short_name,
            std::string const& help)
      : argument_base{ name, short_name, help }
   {
   }

   void assign(std::string const&) override { /* do nothing. */ }
   void store_true() override { val_ = true; }
   bool with_value() const override { return false; }

private:
   bool val_ = false;
};

template <typename T>
inline argument_with_value<T> arg(std::string const& name, char short_name = '\0',
                                  std::string const& help = "")
{
   return argument_with_value<T>{ name, short_name, help };
}

template <typename T>
inline argument_with_value<T> arg(std::string const& name, std::string const& help)
{
   return argument_with_value<T>{ name, '\0', help };
}

inline argument_flag flag(std::string const& name, char short_name = '\0',
                          std::string const& help = "")
{
   return argument_flag{ name, short_name, help };
}

inline argument_flag flag(std::string const& name, std::string const& help)
{
   return argument_flag{ name, '\0', help };
}

template <std::size_t... Idx>
struct index_sequence {
   using next = index_sequence<Idx..., sizeof...(Idx)>;
};

template <std::size_t Nt, std::size_t N>
struct iota {
   using type = typename iota<Nt-1, N-1>::type::next;
};

template <std::size_t Nt>
struct iota<Nt, 0> {
   using type = index_sequence<>;
};

template <std::size_t N>
using make_index_sequence = typename iota<N, N>::type;

template <typename... T> inline void dummy(T...) {}

template <typename... Args>
struct parser
{
   using args_type = std::tuple<typename Args::arg_type...>;

   parser(Args&&... args)
      : args_{ std::forward<Args>(args)... }
   {
      make_lookup_tables(args_, make_index_sequence<sizeof...(Args)>());
   }

   template <typename Tuple, std::size_t... Idx>
   void make_lookup_tables(Tuple& args, index_sequence<Idx...>) {
      dummy( append_to_lookup_table(std::get<Idx>(args))... );
   }

   template <typename Arg>
   int append_to_lookup_table(Arg& arg) {
      std::string const& name = arg.name();
      lookup_.insert({ name, static_cast<argument_base&>(arg) });

      char s = arg.short_name();
      if (s != '\0')
         short_lookup_.insert({ s, static_cast<argument_base&>(arg) });

      return 0;
   }

   void parse(std::vector<std::string> const& args) {
      if (args.empty())
         throw std::runtime_error("argument must be at least one item(s).");

      progname_ = args[0];

      for (auto it = args.begin(); it != args.end(); ++it)
      {
         auto& arg = *it;
         if (arg.substr(0,2)=="--") { // long option
            std::string::size_type pos = arg.find('=',2);
            if (pos==std::string::npos) {
               std::string key = arg.substr(2);
               if (lookup_.count(key) == 0)
                  throw std::runtime_error("unknown option: --" + key);
               argument_base& a = lookup_.at(key).get();
               if (a.with_value()) {
                  // read next argument
                  ++it;
                  std::string val = *it;
                  a.assign(val);
               }
               else {
                  a.store_true();
               }
            }
            else {
               std::string key = arg.substr(2, pos);
               std::string val = arg.substr(pos+1);
               argument_base& a = lookup_.at(key).get();
               if (a.with_value()) {
                  a.assign(val);
               }
               else {
                  a.store_true();
               }
            }
         }
         else if (arg[0] == '-') { // short option
            if (arg.length() < 2) continue;
            char s = arg[1];
            if (short_lookup_.count(s) == 0)
               throw std::runtime_error(std::string("unknown short option: -") + s);
            argument_base& a = short_lookup_.at(s).get();
            if (a.with_value()) {
               ++it;
               std::string val = *it;
               a.assign(val);
            } else {
               a.store_true();
            }
         }
         else { // normal argument
            remains_.push_back(arg);
         }
      }
   }

   std::string const& progname() const { return progname_; }
   args_type const& options() const { return options_; }
   std::vector<std::string> const& remains() const { return remains_; }

private:
   std::tuple<Args...> args_;
   std::unordered_map<std::string, std::reference_wrapper<argument_base>> lookup_;
   std::unordered_map<char,        std::reference_wrapper<argument_base>> short_lookup_;

   std::string progname_;
   args_type options_;
   std::vector<std::string> remains_;
};

template <typename... Args>
parser<Args...> make_parser(Args&&... args) {
   return parser<Args...>{ std::forward<Args>(args)... };
}

} // namespace argparse;
<commit_msg>implemention is done<commit_after>#pragma once

#include <string>
#include <vector>
#include <tuple>
#include <sstream>
#include <type_traits>
#include <functional>
#include <memory>
#include <unordered_map>

namespace argparse {

namespace detail {
    template <typename In, typename Out, bool pass = std::is_convertible<In, Out>::value>
    struct lexical_cast_t;

    template <typename In, typename Out>
    struct lexical_cast_t<In, Out, true> {
        static Out apply(In const& val) {
            return static_cast<Out>(val);
        }
    };

    template <typename In>
    struct lexical_cast_t<In, std::string, false> {
        static std::string apply(In const& val) {
            std::ostringstream osstr;
            osstr << val;
            return osstr.str();
        }
    };

    template <typename Out>
    struct lexical_cast_t<std::string, Out, false> {
        static Out apply(std::string const& val) {
            std::istringstream isstr(val);
            Out out;
            isstr >> out;
            return out;
        }
    };

    template <typename Out, std::size_t N>
    struct lexical_cast_t<char[N], Out, false> {
        static Out apply(char const (&val)[N]) {
            std::istringstream isstr(val);
            Out out;
            isstr >> out;
            return out;
        }
    };

    template <typename Out, std::size_t N>
    struct lexical_cast_t<char const[N], Out, false> {
        static Out apply(char const (&val)[N]) {
            std::istringstream isstr(val);
            Out out;
            isstr >> out;
            return out;
        }
    };
} // namespace detail;

template <typename Out, typename In>
inline Out lexical_cast(In const& val) {
    return detail::lexical_cast_t<In, Out>::apply(val);
}

//

struct argument_base {
   virtual void assign(std::string const& src) = 0;
   virtual void store_true() = 0;
   virtual bool with_value() const = 0;

   argument_base(std::string const& name, char short_name,
                 std::string const& help)
     : name_{name}, short_name_{short_name}, help_{help}
  {
  }

   std::string const& name() const { return name_; }
   char short_name() const { return short_name_; }

private:
   std::string name_;
   char short_name_;
   std::string help_;
};

template <typename T>
struct argument_with_value : public argument_base {
   using arg_type = T;

   argument_with_value(std::string const& name, char short_name,
                       std::string const& help)
      : argument_base{name, short_name, help}
   {
   }

   void assign(std::string const& src) override {
      val_.reset(new T(lexical_cast<T>(src)));
   }

   void store_true() override { /* do nothing. */ }
   bool with_value() const override { return true; }

   T const& get() const {
      if (val_) {
         return *val_;
      }
      else {
         throw std::runtime_error("not initialized");
      }
   }

private:
   std::unique_ptr<T> val_;
};

struct argument_flag : public argument_base {
   using arg_type = bool;

   argument_flag(std::string const& name, char short_name,
            std::string const& help)
      : argument_base{ name, short_name, help }
   {
   }

   void assign(std::string const&) override { /* do nothing. */ }
   void store_true() override { val_ = true; }
   bool with_value() const override { return false; }

   bool get() const { return val_; }

private:
   bool val_ = false;
};

template <typename T>
inline argument_with_value<T> arg(std::string const& name, char short_name = '\0',
                                  std::string const& help = "")
{
   return argument_with_value<T>{ name, short_name, help };
}

template <typename T>
inline argument_with_value<T> arg(std::string const& name, std::string const& help)
{
   return argument_with_value<T>{ name, '\0', help };
}

inline argument_flag flag(std::string const& name, char short_name = '\0',
                          std::string const& help = "")
{
   return argument_flag{ name, short_name, help };
}

inline argument_flag flag(std::string const& name, std::string const& help)
{
   return argument_flag{ name, '\0', help };
}

template <std::size_t... Idx>
struct index_sequence {
   using next = index_sequence<Idx..., sizeof...(Idx)>;
};

template <std::size_t Nt, std::size_t N>
struct iota {
   using type = typename iota<Nt-1, N-1>::type::next;
};

template <std::size_t Nt>
struct iota<Nt, 0> {
   using type = index_sequence<>;
};

template <std::size_t N>
using make_index_sequence = typename iota<N, N>::type;

template <typename... T> inline void dummy(T...) {}

template <typename... Args>
struct parser
{
   using args_type = std::tuple<typename Args::arg_type...>;

   parser(Args&&... args)
      : args_{ std::forward<Args>(args)... }
   {
      make_lookup_tables(args_, make_index_sequence<sizeof...(Args)>());
   }

   template <typename Tuple, std::size_t... Idx>
   void make_lookup_tables(Tuple& args, index_sequence<Idx...>) {
      dummy( append_to_lookup_table(std::get<Idx>(args))... );
   }

   template <typename Arg>
   int append_to_lookup_table(Arg& arg) {
      std::string const& name = arg.name();
      lookup_.insert({ name, static_cast<argument_base&>(arg) });

      char s = arg.short_name();
      if (s != '\0')
         short_lookup_.insert({ s, static_cast<argument_base&>(arg) });

      return 0;
   }

   void parse(std::vector<std::string> const& args) {
      if (args.empty())
         throw std::runtime_error("argument must be at least one item(s).");

      progname_ = args[0];

      for (auto it = args.begin()+1; it != args.end(); ++it)
      {
         auto& arg = *it;
         if (arg.substr(0,2)=="--") { // long option
            std::string::size_type pos = arg.find('=',2);
            if (pos==std::string::npos) {
               std::string key = arg.substr(2);
               if (lookup_.count(key) == 0)
                  throw std::runtime_error("unknown option: --" + key);
               argument_base& a = lookup_.at(key).get();
               if (a.with_value()) {
                  // read next argument
                  ++it;
                  std::string val = *it;
                  a.assign(val);
               }
               else {
                  a.store_true();
               }
            }
            else {
               std::string key = arg.substr(2, pos);
               std::string val = arg.substr(pos+1);
               argument_base& a = lookup_.at(key).get();
               if (a.with_value()) {
                  a.assign(val);
               }
               else {
                  a.store_true();
               }
            }
         }
         else if (arg[0] == '-') { // short option
            if (arg.length() < 2) continue;
            char s = arg[1];
            if (short_lookup_.count(s) == 0)
               throw std::runtime_error(std::string("unknown short option: -") + s);
            argument_base& a = short_lookup_.at(s).get();
            if (a.with_value()) {
               ++it;
               std::string val = *it;
               a.assign(val);
            } else {
               a.store_true();
            }
         }
         else { // normal argument
            remains_.push_back(arg);
         }
      }

      get_values(make_index_sequence<std::tuple_size<args_type>::value>());
   }

   template <size_t... Idx>
   void get_values(index_sequence<Idx...>)
   {
      dummy(get_value(std::get<Idx>(options_), std::get<Idx>(args_))...);
   }

   template <typename Opt, typename Arg>
   int get_value(Opt& opt, Arg& arg) {
      opt = arg.get();
      return 0;
   }

   std::string const& progname() const { return progname_; }
   args_type const& options() const { return options_; }
   std::vector<std::string> const& remains() const { return remains_; }

private:
   std::tuple<Args...> args_;
   std::unordered_map<std::string, std::reference_wrapper<argument_base>> lookup_;
   std::unordered_map<char,        std::reference_wrapper<argument_base>> short_lookup_;

   std::string progname_;
   args_type options_;
   std::vector<std::string> remains_;
};

template <typename... Args>
parser<Args...> make_parser(Args&&... args) {
   return parser<Args...>{ std::forward<Args>(args)... };
}

} // namespace argparse;
<|endoftext|>


<commit_before>/****************************************************************************
 * Copyright (c) 2012-2019 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_DBC.hpp>

#include <Kokkos_View.hpp>

#include <fstream>
#include <random>

enum PointCloudType { filled_box, hollow_box, filled_sphere, hollow_sphere };

template <typename Layout, typename DeviceType>
void writePointCloud(
    Kokkos::View<DataTransferKit::Point *, Layout, DeviceType> random_points,
    std::string const &filename )

{
    static_assert(
        Kokkos::Impl::MemorySpaceAccess<
            Kokkos::HostSpace, typename DeviceType::memory_space>::accessible,
        "The View should be accessible on the Host" );
    std::ofstream file( filename );
    if ( file.is_open() )
    {
        unsigned int const n = random_points.extent( 0 );
        for ( unsigned int i = 0; i < n; ++i )
            file << random_points( i )[0] << " " << random_points( i )[1] << " "
                 << random_points( i )[2] << "\n";
        file.close();
    }
}

template <typename Layout, typename DeviceType>
void filledBoxCloud(
    double const half_edge,
    Kokkos::View<DataTransferKit::Point *, Layout, DeviceType> random_points )
{
    static_assert(
        Kokkos::Impl::MemorySpaceAccess<
            Kokkos::HostSpace, typename DeviceType::memory_space>::accessible,
        "The View should be accessible on the Host" );
    std::uniform_real_distribution<double> distribution( -half_edge,
                                                         half_edge );
    std::default_random_engine generator;
    auto random = [&distribution, &generator]() {
        return distribution( generator );
    };
    unsigned int const n = random_points.extent( 0 );
    for ( unsigned int i = 0; i < n; ++i )
        random_points( i ) = {{random(), random(), random()}};
}

template <typename Layout, typename DeviceType>
void hollowBoxCloud(
    double const half_edge,
    Kokkos::View<DataTransferKit::Point *, Layout, DeviceType> random_points )
{
    static_assert(
        Kokkos::Impl::MemorySpaceAccess<
            Kokkos::HostSpace, typename DeviceType::memory_space>::accessible,
        "The View should be accessible on the Host" );
    std::uniform_real_distribution<double> distribution( -half_edge,
                                                         half_edge );
    std::default_random_engine generator;
    auto random = [&distribution, &generator]() {
        return distribution( generator );
    };
    unsigned int const n = random_points.extent( 0 );
    for ( unsigned int i = 0; i < n; ++i )
    {
        unsigned int face = i % 6;
        switch ( face )
        {
        case 0:
        {
            random_points( i ) = {{-half_edge, random(), random()}};

            break;
        }
        case 1:
        {
            random_points( i ) = {{half_edge, random(), random()}};

            break;
        }
        case 2:
        {
            random_points( i ) = {{random(), -half_edge, random()}};

            break;
        }
        case 3:
        {
            random_points( i ) = {{random(), half_edge, random()}};

            break;
        }
        case 4:
        {
            random_points( i ) = {{random(), random(), -half_edge}};

            break;
        }
        case 5:
        {
            random_points( i ) = {{random(), random(), half_edge}};

            break;
        }
        default:
        {
            throw std::runtime_error( "Your compiler is broken" );
        }
        }
    }
}

template <typename Layout, typename DeviceType>
void filledSphereCloud(
    double const radius,
    Kokkos::View<DataTransferKit::Point *, Layout, DeviceType> random_points )
{
    static_assert(
        Kokkos::Impl::MemorySpaceAccess<
            Kokkos::HostSpace, typename DeviceType::memory_space>::accessible,
        "The View should be accessible on the Host" );
    std::default_random_engine generator;

    std::uniform_real_distribution<double> distribution( -radius, radius );
    auto random = [&distribution, &generator]() {
        return distribution( generator );
    };

    unsigned int const n = random_points.extent( 0 );
    for ( unsigned int i = 0; i < n; ++i )
    {
        bool point_accepted = false;
        while ( !point_accepted )
        {
            double const x = random();
            double const y = random();
            double const z = random();

            // Only accept points that are in the sphere
            if ( std::sqrt( x * x + y * y + z * z ) <= radius )
            {
                random_points( i ) = {{x, y, z}};
                point_accepted = true;
            }
        }
    }
}

template <typename Layout, typename DeviceType>
void hollowSphereCloud(
    double const radius,
    Kokkos::View<DataTransferKit::Point *, Layout, DeviceType> random_points )
{
    static_assert(
        Kokkos::Impl::MemorySpaceAccess<
            Kokkos::HostSpace, typename DeviceType::memory_space>::accessible,
        "The View should be accessible on the Host" );
    std::default_random_engine generator;

    std::uniform_real_distribution<double> distribution( -1., 1. );
    auto random = [&distribution, &generator]() {
        return distribution( generator );
    };

    unsigned int const n = random_points.extent( 0 );
    for ( unsigned int i = 0; i < n; ++i )
    {
        double const x = random();
        double const y = random();
        double const z = random();
        double const norm = std::sqrt( x * x + y * y + z * z );

        random_points( i ) = {
            {radius * x / norm, radius * y / norm, radius * z / norm}};
    }
}

template <typename DeviceType>
void generatePointCloud(
    PointCloudType const point_cloud_type, double const length,
    Kokkos::View<DataTransferKit::Point *, DeviceType> random_points )
{
    auto random_points_host = Kokkos::create_mirror_view( random_points );
    if ( point_cloud_type == PointCloudType::filled_box )
    {
        filledBoxCloud( length, random_points_host );
    }
    else if ( point_cloud_type == PointCloudType::hollow_box )
    {
        hollowBoxCloud( length, random_points_host );
    }
    else if ( point_cloud_type == PointCloudType::filled_sphere )
    {
        filledSphereCloud( length, random_points_host );
    }
    else if ( point_cloud_type == PointCloudType::hollow_sphere )
    {
        hollowSphereCloud( length, random_points_host );
    }
    else
    {
        throw DataTransferKit::DataTransferKitNotImplementedException();
    }
    Kokkos::deep_copy( random_points, random_points_host );
}
<commit_msg>Load point cloud from a file<commit_after>/****************************************************************************
 * Copyright (c) 2012-2019 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_DBC.hpp>

#include <Kokkos_View.hpp>

#include <fstream>
#include <random>

enum PointCloudType { filled_box, hollow_box, filled_sphere, hollow_sphere };

template <typename Layout, typename DeviceType>
void writePointCloud(
    Kokkos::View<DataTransferKit::Point *, Layout, DeviceType> random_points,
    std::string const &filename )

{
    static_assert(
        Kokkos::Impl::MemorySpaceAccess<
            Kokkos::HostSpace, typename DeviceType::memory_space>::accessible,
        "The View should be accessible on the Host" );
    std::ofstream file( filename );
    if ( file.is_open() )
    {
        unsigned int const n = random_points.extent( 0 );
        for ( unsigned int i = 0; i < n; ++i )
            file << random_points( i )[0] << " " << random_points( i )[1] << " "
                 << random_points( i )[2] << "\n";
        file.close();
    }
}

template <typename Layout, typename DeviceType>
void filledBoxCloud(
    double const half_edge,
    Kokkos::View<DataTransferKit::Point *, Layout, DeviceType> random_points )
{
    static_assert(
        Kokkos::Impl::MemorySpaceAccess<
            Kokkos::HostSpace, typename DeviceType::memory_space>::accessible,
        "The View should be accessible on the Host" );
    std::uniform_real_distribution<double> distribution( -half_edge,
                                                         half_edge );
    std::default_random_engine generator;
    auto random = [&distribution, &generator]() {
        return distribution( generator );
    };
    unsigned int const n = random_points.extent( 0 );
    for ( unsigned int i = 0; i < n; ++i )
        random_points( i ) = {{random(), random(), random()}};
}

template <typename Layout, typename DeviceType>
void hollowBoxCloud(
    double const half_edge,
    Kokkos::View<DataTransferKit::Point *, Layout, DeviceType> random_points )
{
    static_assert(
        Kokkos::Impl::MemorySpaceAccess<
            Kokkos::HostSpace, typename DeviceType::memory_space>::accessible,
        "The View should be accessible on the Host" );
    std::uniform_real_distribution<double> distribution( -half_edge,
                                                         half_edge );
    std::default_random_engine generator;
    auto random = [&distribution, &generator]() {
        return distribution( generator );
    };
    unsigned int const n = random_points.extent( 0 );
    for ( unsigned int i = 0; i < n; ++i )
    {
        unsigned int face = i % 6;
        switch ( face )
        {
        case 0:
        {
            random_points( i ) = {{-half_edge, random(), random()}};

            break;
        }
        case 1:
        {
            random_points( i ) = {{half_edge, random(), random()}};

            break;
        }
        case 2:
        {
            random_points( i ) = {{random(), -half_edge, random()}};

            break;
        }
        case 3:
        {
            random_points( i ) = {{random(), half_edge, random()}};

            break;
        }
        case 4:
        {
            random_points( i ) = {{random(), random(), -half_edge}};

            break;
        }
        case 5:
        {
            random_points( i ) = {{random(), random(), half_edge}};

            break;
        }
        default:
        {
            throw std::runtime_error( "Your compiler is broken" );
        }
        }
    }
}

template <typename Layout, typename DeviceType>
void filledSphereCloud(
    double const radius,
    Kokkos::View<DataTransferKit::Point *, Layout, DeviceType> random_points )
{
    static_assert(
        Kokkos::Impl::MemorySpaceAccess<
            Kokkos::HostSpace, typename DeviceType::memory_space>::accessible,
        "The View should be accessible on the Host" );
    std::default_random_engine generator;

    std::uniform_real_distribution<double> distribution( -radius, radius );
    auto random = [&distribution, &generator]() {
        return distribution( generator );
    };

    unsigned int const n = random_points.extent( 0 );
    for ( unsigned int i = 0; i < n; ++i )
    {
        bool point_accepted = false;
        while ( !point_accepted )
        {
            double const x = random();
            double const y = random();
            double const z = random();

            // Only accept points that are in the sphere
            if ( std::sqrt( x * x + y * y + z * z ) <= radius )
            {
                random_points( i ) = {{x, y, z}};
                point_accepted = true;
            }
        }
    }
}

template <typename Layout, typename DeviceType>
void hollowSphereCloud(
    double const radius,
    Kokkos::View<DataTransferKit::Point *, Layout, DeviceType> random_points )
{
    static_assert(
        Kokkos::Impl::MemorySpaceAccess<
            Kokkos::HostSpace, typename DeviceType::memory_space>::accessible,
        "The View should be accessible on the Host" );
    std::default_random_engine generator;

    std::uniform_real_distribution<double> distribution( -1., 1. );
    auto random = [&distribution, &generator]() {
        return distribution( generator );
    };

    unsigned int const n = random_points.extent( 0 );
    for ( unsigned int i = 0; i < n; ++i )
    {
        double const x = random();
        double const y = random();
        double const z = random();
        double const norm = std::sqrt( x * x + y * y + z * z );

        random_points( i ) = {
            {radius * x / norm, radius * y / norm, radius * z / norm}};
    }
}

template <typename DeviceType>
void generatePointCloud(
    PointCloudType const point_cloud_type, double const length,
    Kokkos::View<DataTransferKit::Point *, DeviceType> random_points )
{
    auto random_points_host = Kokkos::create_mirror_view( random_points );
    if ( point_cloud_type == PointCloudType::filled_box )
    {
        filledBoxCloud( length, random_points_host );
    }
    else if ( point_cloud_type == PointCloudType::hollow_box )
    {
        hollowBoxCloud( length, random_points_host );
    }
    else if ( point_cloud_type == PointCloudType::filled_sphere )
    {
        filledSphereCloud( length, random_points_host );
    }
    else if ( point_cloud_type == PointCloudType::hollow_sphere )
    {
        hollowSphereCloud( length, random_points_host );
    }
    else
    {
        throw DataTransferKit::DataTransferKitNotImplementedException();
    }
    Kokkos::deep_copy( random_points, random_points_host );
}

template <typename DeviceType>
void loadPointCloud(
    std::string const &filename,
    Kokkos::View<DataTransferKit::Point *, DeviceType> &random_points )
{
    std::ifstream file( filename );
    if ( file.is_open() )
    {
        int size = -1;
        file >> size;
        DTK_REQUIRE( size > 0 );
        Kokkos::realloc( random_points, size );
        auto random_points_host = Kokkos::create_mirror_view( random_points );
        for ( int i = 0; i < size; ++i )
            for ( int j = 0; j < 3; ++j )
                file >> random_points( i )[j];
        Kokkos::deep_copy( random_points, random_points_host );
    }
    else
    {
        throw std::runtime_error( "Cannot open file" );
    }
}
<|endoftext|>


<commit_before>/*
    Auto away-presence setter-class
    Copyright (C) 2011  Martin Klapetek <martin.klapetek@gmail.com>

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

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

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include "autoaway.h"

#include <TelepathyQt4/AccountManager>
#include <TelepathyQt4/AccountSet>

#include <KDebug>
#include <KIdleTime>
#include <KConfig>
#include <KConfigGroup>

AutoAway::AutoAway(const Tp::AccountManagerPtr& am, QObject* parent)
    : QObject(parent),
      m_awayTimeoutId(-1),
      m_extAwayTimeoutId(-1)
{
    readConfig();
    m_accountManager = am;
    m_prevPresence = Tp::Presence::available();

    connect(KIdleTime::instance(), SIGNAL(timeoutReached(int)),
            this, SLOT(timeoutReached(int)));

    connect(KIdleTime::instance(), SIGNAL(resumingFromIdle()),
            this, SLOT(backFromIdle()));
}

AutoAway::~AutoAway()
{
}

void AutoAway::timeoutReached(int id)
{
    KIdleTime::instance()->catchNextResumeEvent();
    if (id == m_awayTimeoutId) {
        if (!m_accountManager->onlineAccounts()->accounts().isEmpty()) {
            if (m_accountManager->onlineAccounts()->accounts().first()->currentPresence().type() != Tp::Presence::away().type() ||
                m_accountManager->onlineAccounts()->accounts().first()->currentPresence().type() != Tp::Presence::xa().type() ||
                m_accountManager->onlineAccounts()->accounts().first()->currentPresence().type() != Tp::Presence::hidden().type()) {

                m_prevPresence = m_accountManager->onlineAccounts()->accounts().first()->currentPresence();
                emit setPresence(Tp::Presence::away());

            }
        } else if (id == m_extAwayTimeoutId) {
            if (!m_accountManager->onlineAccounts()->accounts().isEmpty()) {
                if (m_accountManager->onlineAccounts()->accounts().first()->currentPresence().type() == Tp::Presence::away().type()) {
                    emit setPresence(Tp::Presence::xa());
                }
            }
        }
    }
}

void AutoAway::backFromIdle()
{
    kDebug();
    emit setPresence(m_prevPresence);
}

void AutoAway::readConfig()
{
    KSharedConfigPtr config = KSharedConfig::openConfig(QLatin1String("ktelepathyrc"));
    KConfigGroup kdedConfig = config->group("KDED");

    bool autoAwayEnabled = kdedConfig.readEntry("autoAwayEnabled", true);
    bool autoXAEnabled = kdedConfig.readEntry("autoXAEnabled", true);

    if (autoAwayEnabled) {
        int awayTime = kdedConfig.readEntry("awayAfter", 5);
        m_awayTimeoutId = KIdleTime::instance()->addIdleTimeout(awayTime * 60 * 1000);
    } else if (!autoAwayEnabled && m_awayTimeoutId != -1) {
        KIdleTime::instance()->removeAllIdleTimeouts();
    }
    if (autoAwayEnabled && autoXAEnabled) {
        int xaTime = kdedConfig.readEntry("xaAfter", 15);
        m_extAwayTimeoutId = KIdleTime::instance()->addIdleTimeout(xaTime * 60 * 1000);
    }
}

void AutoAway::onSettingsChanged()
{
    readConfig();
}
<commit_msg>Prevent multiple timeouts being added on each config change<commit_after>/*
    Auto away-presence setter-class
    Copyright (C) 2011  Martin Klapetek <martin.klapetek@gmail.com>

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

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

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include "autoaway.h"

#include <TelepathyQt4/AccountManager>
#include <TelepathyQt4/AccountSet>

#include <KDebug>
#include <KIdleTime>
#include <KConfig>
#include <KConfigGroup>

AutoAway::AutoAway(const Tp::AccountManagerPtr& am, QObject* parent)
    : QObject(parent),
      m_awayTimeoutId(-1),
      m_extAwayTimeoutId(-1)
{
    readConfig();
    m_accountManager = am;
    m_prevPresence = Tp::Presence::available();

    connect(KIdleTime::instance(), SIGNAL(timeoutReached(int)),
            this, SLOT(timeoutReached(int)));

    connect(KIdleTime::instance(), SIGNAL(resumingFromIdle()),
            this, SLOT(backFromIdle()));
}

AutoAway::~AutoAway()
{
}

void AutoAway::timeoutReached(int id)
{
    KIdleTime::instance()->catchNextResumeEvent();
    if (id == m_awayTimeoutId) {
        if (!m_accountManager->onlineAccounts()->accounts().isEmpty()) {
            if (m_accountManager->onlineAccounts()->accounts().first()->currentPresence().type() != Tp::Presence::away().type() ||
                m_accountManager->onlineAccounts()->accounts().first()->currentPresence().type() != Tp::Presence::xa().type() ||
                m_accountManager->onlineAccounts()->accounts().first()->currentPresence().type() != Tp::Presence::hidden().type()) {

                m_prevPresence = m_accountManager->onlineAccounts()->accounts().first()->currentPresence();
                emit setPresence(Tp::Presence::away());

            }
        } else if (id == m_extAwayTimeoutId) {
            if (!m_accountManager->onlineAccounts()->accounts().isEmpty()) {
                if (m_accountManager->onlineAccounts()->accounts().first()->currentPresence().type() == Tp::Presence::away().type()) {
                    emit setPresence(Tp::Presence::xa());
                }
            }
        }
    }
}

void AutoAway::backFromIdle()
{
    kDebug();
    emit setPresence(m_prevPresence);
}

void AutoAway::readConfig()
{
    KSharedConfigPtr config = KSharedConfig::openConfig(QLatin1String("ktelepathyrc"));
    KConfigGroup kdedConfig = config->group("KDED");

    bool autoAwayEnabled = kdedConfig.readEntry("autoAwayEnabled", true);
    bool autoXAEnabled = kdedConfig.readEntry("autoXAEnabled", true);

    //remove all our timeouts and only readd them if auto-away is enabled
    //WARNING: can't use removeAllTimeouts because this runs inside KDED, it would remove other KDED timeouts as well
    KIdleTime::instance()->removeIdleTimeout(m_awayTimeoutId);
    KIdleTime::instance()->removeIdleTimeout(m_extAwayTimeoutId);

    if (autoAwayEnabled) {
        int awayTime = kdedConfig.readEntry("awayAfter", 5);
        m_awayTimeoutId = KIdleTime::instance()->addIdleTimeout(awayTime * 60 * 1000);
    }
    if (autoAwayEnabled && autoXAEnabled) {
        int xaTime = kdedConfig.readEntry("xaAfter", 15);
        m_extAwayTimeoutId = KIdleTime::instance()->addIdleTimeout(xaTime * 60 * 1000);
    }
}

void AutoAway::onSettingsChanged()
{
    readConfig();
}
<|endoftext|>


<commit_before>/** \file    extract_keywords_for_translation.cc
 *  \brief   A tool for extracting keywords that need to be translated.  The keywords and any possibly pre-existing
 *           translations will be stored in a SQL database.
 *  \author  Dr. Johannes Ruscheinski
 */

/*
    Copyright (C) 2016, Library of the University of Tübingen

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as
    published by the Free Software Foundation, either version 3 of the
    License, or (at your option) any later version.

    This program 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 Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <iostream>
#include <string>
#include <unordered_set>
#include <utility>
#include <vector>
#include <cstdlib>
#include "Compiler.h"
#include "DbConnection.h"
#include "DbResultSet.h"
#include "DbRow.h"
#include "DirectoryEntry.h"
#include "IniFile.h"
#include "Leader.h"
#include "MarcUtil.h"
#include "StringUtil.h"
#include "Subfields.h"
#include "TranslationUtil.h"
#include "util.h"

void Usage() {
    std::cerr << "Usage: " << progname << " title_input norm_data_input\n";
    std::exit(EXIT_FAILURE);
}

static std::unordered_set<std::string> *shared_norm_data_control_numbers;

bool RecordKeywordControlNumbers(MarcUtil::Record * const record, XmlWriter * const /*xml_writer*/,
				 std::string * const /* err_msg */)
{
    std::vector<std::string> keyword_tags;
    StringUtil::Split("600:610:611:630:650:653:656", ':', &keyword_tags);
    const std::vector<std::string> &fields(record->getFields());
    const std::vector<DirectoryEntry> &dir_entries(record->getDirEntries());
    for (const auto &keyword_tag : keyword_tags) {
	const ssize_t start_index(record->getFieldIndex(keyword_tag));
	if (start_index == -1)
	    continue;

        for (size_t index(start_index); index < dir_entries.size() and dir_entries[index].getTag() == keyword_tag; ++index) {
            const Subfields subfields(fields[index]);
            const auto begin_end(subfields.getIterators('0'));
            for (auto subfield0(begin_end.first); subfield0 != begin_end.second; ++subfield0) {
                if (not StringUtil::StartsWith(subfield0->second, "(DE-576)"))
                    continue;

                const std::string topic_id(subfield0->second.substr(8));
		shared_norm_data_control_numbers->insert(topic_id);
            }
        }
    }

    return true;
}

void ExtractKeywordNormdataControlNumbers(File * const marc_input,
					  std::unordered_set<std::string> * const norm_data_control_numbers)
{
    const size_t orig_size(norm_data_control_numbers->size());

    shared_norm_data_control_numbers = norm_data_control_numbers;
    std::string err_msg;
    if (not MarcUtil::ProcessRecords(marc_input, RecordKeywordControlNumbers, nullptr, &err_msg))
	Error("error while extracting keyword control numbers for \"" + marc_input->getPath() + "\": " + err_msg);

    std::cerr << "Found " << (norm_data_control_numbers->size() - orig_size) << " new keyword control numbers in "
	      << marc_input->getPath() << '\n';
}

static unsigned keyword_count, translation_count;
static DbConnection *shared_connection;

bool ExtractTranslations(MarcUtil::Record * const record, XmlWriter * const /*xml_writer*/, std::string * const /* err_msg */) {
    const std::vector<std::string> &fields(record->getFields());
    if (shared_norm_data_control_numbers->find(fields[0]) == shared_norm_data_control_numbers->cend())
	return true; // Not one of the records w/ a keyword used in our title data.

    const ssize_t _150_index(record->getFieldIndex("150"));
    if (_150_index == -1)
	return true;
    const Subfields _150_subfields(fields[_150_index]);
    const std::string german_text(_150_subfields.getFirstSubfieldValue('a'));
    if (unlikely(german_text.empty()))
	return true;
    ++keyword_count;

    std::vector<std::pair<std::string, std::string>> text_and_language_codes;
    text_and_language_codes.emplace_back(std::make_pair(german_text, "deu"));

    // Find translations:
    const ssize_t first_750_index(record->getFieldIndex("750"));
    if (first_750_index != -1) {
	const std::vector<DirectoryEntry> &dir_entries(record->getDirEntries());
        for (size_t index(first_750_index); index < dir_entries.size() and dir_entries[index].getTag() == "750"; ++index) {
	    const Subfields _750_subfields(fields[index]);
	    auto start_end(_750_subfields.getIterators('9'));
	    if (start_end.first == start_end.second)
		continue;
	    std::string language_code, association;
	    for (auto code_and_value(start_end.first); code_and_value != start_end.second; ++code_and_value) {
		if (StringUtil::StartsWith(code_and_value->second, "L:"))
		    language_code = code_and_value->second.substr(2);
		else if (StringUtil::StartsWith(code_and_value->second, "Z:"))
		    association = code_and_value->second.substr(2);
	    }
	    if (not language_code.empty()) {
		++translation_count;
		text_and_language_codes.emplace_back(std::make_pair(_750_subfields.getFirstSubfieldValue('a'), language_code));
	    }
        }
    }

    // Update the database.
    const std::string id(TranslationUtil::GetId(shared_connection, german_text));
    for (const auto &text_and_language_code : text_and_language_codes) {
	const std::string REPLACE_STMT("REPLACE INTO translations SET id=" + id + ", language_code=\""
				       + text_and_language_code.second + "\", category=\"keywords\", preexists=TRUE, text=\""
				       + shared_connection->escapeString(text_and_language_code.first) + "\"");
	if (not shared_connection->query(REPLACE_STMT))
	    Error("Insert failed: " + REPLACE_STMT + " (" + shared_connection->getLastErrorMessage() + ")");
    }

    return true;
}

void ExtractTranslationTerms(File * const norm_data_input, DbConnection * const connection) {
    shared_connection = connection;

    std::string err_msg;
    if (not MarcUtil::ProcessRecords(norm_data_input, ExtractTranslations, nullptr, &err_msg))
	Error("error while extracting translations from \"" + norm_data_input->getPath() + "\": " + err_msg);

    std::cerr << "Added " << keyword_count << " to the translation database.\n";
    std::cerr << "Found " << translation_count << " translations in the norm data.\n";
}

const std::string CONF_FILE_PATH("/var/lib/tuelib/translations.conf");

int main(int argc, char **argv) {
    progname = argv[0];

    if (argc != 3)
        Usage();

    const std::string marc_input_filename(argv[1]);
    File marc_input(marc_input_filename, "rm");
    if (not marc_input)
        Error("can't open \"" + marc_input_filename + "\" for reading!");

    const std::string norm_data_marc_input_filename(argv[2]);
    File norm_data_marc_input(norm_data_marc_input_filename, "rm");
    if (not norm_data_marc_input)
        Error("can't open \"" + norm_data_marc_input_filename + "\" for reading!");

    try {
	const IniFile ini_file(CONF_FILE_PATH);
	const std::string sql_database(ini_file.getString("", "sql_database"));
	const std::string sql_username(ini_file.getString("", "sql_username"));
	const std::string sql_password(ini_file.getString("", "sql_password"));
	DbConnection db_connection(sql_database, sql_username, sql_password);

	std::unordered_set<std::string> norm_data_control_numbers;
	ExtractKeywordNormdataControlNumbers(&marc_input, &norm_data_control_numbers);
	ExtractTranslationTerms(&norm_data_marc_input, &db_connection);
    } catch (const std::exception &x) {
	Error("caught exception: " + std::string(x.what()));
    }
}
<commit_msg>We now include 'lcsh' and 'ram' "translations" as well as German synonyms from 450$a subfields.<commit_after>/** \file    extract_keywords_for_translation.cc
 *  \brief   A tool for extracting keywords that need to be translated.  The keywords and any possibly pre-existing
 *           translations will be stored in a SQL database.
 *  \author  Dr. Johannes Ruscheinski
 */

/*
    Copyright (C) 2016, Library of the University of Tübingen

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as
    published by the Free Software Foundation, either version 3 of the
    License, or (at your option) any later version.

    This program 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 Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <iostream>
#include <string>
#include <unordered_set>
#include <utility>
#include <vector>
#include <cstdlib>
#include "Compiler.h"
#include "DbConnection.h"
#include "DbResultSet.h"
#include "DbRow.h"
#include "DirectoryEntry.h"
#include "IniFile.h"
#include "Leader.h"
#include "MarcUtil.h"
#include "StringUtil.h"
#include "Subfields.h"
#include "TimeUtil.h"
#include "TranslationUtil.h"
#include "WallClockTimer.h"
#include "util.h"

void Usage() {
    std::cerr << "Usage: " << progname << " title_input norm_data_input\n";
    std::exit(EXIT_FAILURE);
}

static std::unordered_set<std::string> *shared_norm_data_control_numbers;

bool RecordKeywordControlNumbers(MarcUtil::Record * const record, XmlWriter * const /*xml_writer*/,
				 std::string * const /* err_msg */)
{
    std::vector<std::string> keyword_tags;
    StringUtil::Split("600:610:611:630:650:653:656", ':', &keyword_tags);
    const std::vector<std::string> &fields(record->getFields());
    const std::vector<DirectoryEntry> &dir_entries(record->getDirEntries());
    for (const auto &keyword_tag : keyword_tags) {
	const ssize_t start_index(record->getFieldIndex(keyword_tag));
	if (start_index == -1)
	    continue;

        for (size_t index(start_index); index < dir_entries.size() and dir_entries[index].getTag() == keyword_tag; ++index) {
            const Subfields subfields(fields[index]);
            const auto begin_end(subfields.getIterators('0'));
            for (auto subfield0(begin_end.first); subfield0 != begin_end.second; ++subfield0) {
                if (not StringUtil::StartsWith(subfield0->second, "(DE-576)"))
                    continue;

                const std::string topic_id(subfield0->second.substr(8));
		shared_norm_data_control_numbers->insert(topic_id);
            }
        }
    }

    return true;
}

void ExtractKeywordNormdataControlNumbers(File * const marc_input,
					  std::unordered_set<std::string> * const norm_data_control_numbers)
{
    const size_t orig_size(norm_data_control_numbers->size());

    shared_norm_data_control_numbers = norm_data_control_numbers;
    std::string err_msg;
    if (not MarcUtil::ProcessRecords(marc_input, RecordKeywordControlNumbers, nullptr, &err_msg))
	Error("error while extracting keyword control numbers for \"" + marc_input->getPath() + "\": " + err_msg);

    std::cerr << "Found " << (norm_data_control_numbers->size() - orig_size) << " new keyword control numbers in "
	      << marc_input->getPath() << '\n';
}

static unsigned keyword_count, translation_count, additional_hits, synonym_count;
static DbConnection *shared_connection;

bool ExtractTranslations(MarcUtil::Record * const record, XmlWriter * const /*xml_writer*/, std::string * const /* err_msg */) {
    const std::vector<std::string> &fields(record->getFields());
    if (shared_norm_data_control_numbers->find(fields[0]) == shared_norm_data_control_numbers->cend())
	return true; // Not one of the records w/ a keyword used in our title data.

    // Extract original German entry:
    const ssize_t _150_index(record->getFieldIndex("150"));
    if (_150_index == -1)
	return true;
    const Subfields _150_subfields(fields[_150_index]);
    const std::string german_text(_150_subfields.getFirstSubfieldValue('a'));
    if (unlikely(german_text.empty()))
	return true;
    ++keyword_count;

    std::vector<std::pair<std::string, std::string>> text_and_language_codes;
    text_and_language_codes.emplace_back(std::make_pair(german_text, "deu"));

    // Look for German synonyms:
    const std::vector<DirectoryEntry> &dir_entries(record->getDirEntries());
    ssize_t _450_index(record->getFieldIndex("450"));
    if (_450_index != -1) {
	for (/* Intentionally empty! */;
	     static_cast<size_t>(_450_index) < fields.size() and dir_entries[_450_index].getTag() == "450"; ++_450_index)
        {
	    const Subfields _450_subfields(fields[_450_index]);
	    if (_450_subfields.hasSubfield('a')) {
		text_and_language_codes.emplace_back(std::make_pair(_450_subfields.getFirstSubfieldValue('a'), "deu"));
		++synonym_count;
	    }
	}
    }

    // Find translations:
    const ssize_t first_750_index(record->getFieldIndex("750"));
    if (first_750_index != -1) {
        for (size_t index(first_750_index); index < dir_entries.size() and dir_entries[index].getTag() == "750"; ++index) {
	    const Subfields _750_subfields(fields[index]);
	    auto start_end(_750_subfields.getIterators('9'));
	    if (start_end.first == start_end.second)
		continue;
	    std::string language_code;
	    for (auto code_and_value(start_end.first); code_and_value != start_end.second; ++code_and_value) {
		if (StringUtil::StartsWith(code_and_value->second, "L:"))
		    language_code = code_and_value->second.substr(2);
	    }
	    if (language_code.empty() and _750_subfields.hasSubfield('2')) {
		const std::string _750_2(_750_subfields.getFirstSubfieldValue('2'));
		if (_750_2 == "lcsh")
		    language_code = "eng";
		else if (_750_2 == "ram")
		    language_code ="fra";
		if (not language_code.empty())
		    ++additional_hits;
            }
	    if (not language_code.empty()) {
		++translation_count;
		text_and_language_codes.emplace_back(std::make_pair(_750_subfields.getFirstSubfieldValue('a'), language_code));
	    }
        }
    }

    // Update the database.
    const std::string id(TranslationUtil::GetId(shared_connection, german_text));
    for (const auto &text_and_language_code : text_and_language_codes) {
	const std::string REPLACE_STMT("REPLACE INTO translations SET id=" + id + ", language_code=\""
				       + text_and_language_code.second + "\", category=\"keywords\", preexists=TRUE, text=\""
				       + shared_connection->escapeString(text_and_language_code.first) + "\"");
	if (not shared_connection->query(REPLACE_STMT))
	    Error("Insert failed: " + REPLACE_STMT + " (" + shared_connection->getLastErrorMessage() + ")");
    }

    return true;
}

void ExtractTranslationTerms(File * const norm_data_input, DbConnection * const connection) {
    shared_connection = connection;

    std::string err_msg;
    if (not MarcUtil::ProcessRecords(norm_data_input, ExtractTranslations, nullptr, &err_msg))
	Error("error while extracting translations from \"" + norm_data_input->getPath() + "\": " + err_msg);

    std::cerr << "Added " << keyword_count << " to the translation database.\n";
    std::cerr << "Found " << translation_count << " translations in the norm data. (" << additional_hits
	      << " due to 'ram' and 'lcsh' entries.)\n";
    std::cerr << "Found " << synonym_count << " synonym entries.\n";
}

const std::string CONF_FILE_PATH("/var/lib/tuelib/translations.conf");

int main(int argc, char **argv) {
    ::progname = argv[0];

    if (argc != 3)
        Usage();

    WallClockTimer timer(WallClockTimer::CUMULATIVE_WITH_AUTO_START);

    const std::string marc_input_filename(argv[1]);
    File marc_input(marc_input_filename, "rm");
    if (not marc_input)
        Error("can't open \"" + marc_input_filename + "\" for reading!");

    const std::string norm_data_marc_input_filename(argv[2]);
    File norm_data_marc_input(norm_data_marc_input_filename, "rm");
    if (not norm_data_marc_input)
        Error("can't open \"" + norm_data_marc_input_filename + "\" for reading!");

    try {
	const IniFile ini_file(CONF_FILE_PATH);
	const std::string sql_database(ini_file.getString("", "sql_database"));
	const std::string sql_username(ini_file.getString("", "sql_username"));
	const std::string sql_password(ini_file.getString("", "sql_password"));
	DbConnection db_connection(sql_database, sql_username, sql_password);

	std::unordered_set<std::string> norm_data_control_numbers;
	ExtractKeywordNormdataControlNumbers(&marc_input, &norm_data_control_numbers);
	ExtractTranslationTerms(&norm_data_marc_input, &db_connection);

	timer.stop();
	std::cout << ::progname << ": execution time: " << TimeUtil::FormatTime(timer.getTimeInMilliseconds()) << ".\n";
    } catch (const std::exception &x) {
	Error("caught exception: " + std::string(x.what()));
    }
}
<|endoftext|>


<commit_before>#include "ironbee.hpp"

#include <ironbee/config.h>
#include <ironbee/mpool.h>
#include <ironbee/release.h>
#include <ironbee/debug.h>
#include <ironbee/util.h>
#include <ironbee/state_notify.h>

#include <boost/lexical_cast.hpp>

#include <stdexcept>
#include <string>

using namespace std;

namespace  {

void expect_ok(ib_status_t rc, const char* message)
{
  if (rc != IB_OK) {
    throw runtime_error(
      string("Error (") + ib_status_to_string(rc) + "): " + message
    );
  }
}

ib_conndata_t* buffer_to_conndata(
  ib_conn_t*               conn,
  const IronBee::buffer_t& buffer
)
{
  ib_conndata_t* conndata;
  // We hope IronBee eventually destroys this...
  expect_ok(ib_conn_data_create(conn, &conndata, buffer.length),
    "Allocating connection data."
  );
  conndata->dlen = buffer.length;
  std::copy(
    buffer.data, buffer.data + buffer.length,
    reinterpret_cast<char*>(conndata->data)
  );

  return conndata;
}

}

namespace IronBee {

IronBee::IronBee() :
  m_server {
    IB_SERVER_HEADER_DEFAULTS,
    "cpp_ironbee"
  }
{
  // Trace to stderr.
  ib_trace_init(NULL);

  // Initialize.
  expect_ok(ib_initialize(), "Initializing IronBee.");
  {
    ib_engine_t* engine;
    expect_ok(ib_engine_create(&engine, &m_server), "Creating engine.");
    m_ironbee.reset(engine, &ib_engine_destroy);
  }
  expect_ok(ib_engine_init(m_ironbee.get()), "Initializing engine.");
}

void IronBee::load_config(const std::string& config_path)
{
  boost::shared_ptr<ib_cfgparser_t> parser;

  expect_ok(ib_state_notify_cfg_started(m_ironbee.get()),
    "Starting config."
  );
  {
    ib_cfgparser_t* cp;
    expect_ok(ib_cfgparser_create(&cp, m_ironbee.get()),
      "Creating config parser."
    );
    parser.reset(cp, &ib_cfgparser_destroy);
  }

  expect_ok(ib_cfgparser_parse(parser.get(), config_path.c_str()),
    "Parsing config file."
  );

  ib_state_notify_cfg_finished(m_ironbee.get());

  // Do some sanity checks.
  auto ctx = ib_context_main(m_ironbee.get());
  if (! ctx) {
    throw runtime_error("IronBee has no main context.");
  }
  if (ib_context_get_engine(ctx) != m_ironbee.get()) {
    throw runtime_error("IronBee has corrupt context.");
  }
}

IronBee::connection_p IronBee::open_connection(
  const buffer_t&    local_ip,
  uint16_t           local_port,
  const buffer_t&    remote_ip,
  uint16_t           remote_port
)
{
  return IronBee::connection_p(new Connection(
    *this,
    local_ip,
    local_port,
    remote_ip,
    remote_port
  ));
}

IronBee::connection_p IronBee::open_connection(const input_t& input)
{
  return open_connection(
    input.local_ip,
    input.local_port,
    input.remote_ip,
    input.remote_port
  );
}

IronBee::Connection::Connection(
  IronBee&           ib,
  const buffer_t&    local_ip,
  uint16_t           local_port,
  const buffer_t&    remote_ip,
  uint16_t           remote_port
) :
  m_ib(ib)
{
  expect_ok(ib_conn_create(m_ib.m_ironbee.get(), &m_connection, NULL),
    "Creating connection."
  );

  m_local_ip                 = local_ip.to_s();
  m_remote_ip                = remote_ip.to_s();
  m_connection->local_ipstr  = m_local_ip.c_str();
  m_connection->local_port   = local_port;
  m_connection->remote_ipstr = m_remote_ip.c_str();
  m_connection->remote_port  = remote_port;

  expect_ok(
    ib_state_notify_conn_opened(
      m_ib.m_ironbee.get(),
      m_connection
    ),
    "Opening connection."
  );
}

IronBee::Connection::~Connection()
{
  if (m_connection) {
    close();
  }
}

void IronBee::Connection::close()
{
  expect_ok(
    ib_state_notify_conn_closed(m_ib.m_ironbee.get(), m_connection),
    "Closing connection."
  );
  m_connection = NULL;
}

void IronBee::Connection::data_in(const buffer_t& data)
{
  auto conndata = buffer_to_conndata(
    m_connection,
    data
  );

  expect_ok(
    ib_state_notify_conn_data_in(
        m_ib.m_ironbee.get(),
        conndata,
        NULL
    ),
    "Connection data in."
  );
}

void IronBee::Connection::data_out(const buffer_t& data)
{
  auto conndata = buffer_to_conndata(
    m_connection,
    data
  );

  expect_ok(
    ib_state_notify_conn_data_out(
      m_ib.m_ironbee.get(),
      conndata,
      NULL
    ),
    "Connection data in."
  );
}

} // IronBee
<commit_msg>ibcli_cpp: Update to match recent API changes.<commit_after>#include "ironbee.hpp"

#include <ironbee/config.h>
#include <ironbee/mpool.h>
#include <ironbee/release.h>
#include <ironbee/debug.h>
#include <ironbee/util.h>
#include <ironbee/state_notify.h>

#include <boost/lexical_cast.hpp>

#include <stdexcept>
#include <string>

using namespace std;

namespace  {

void expect_ok(ib_status_t rc, const char* message)
{
  if (rc != IB_OK) {
    throw runtime_error(
      string("Error (") + ib_status_to_string(rc) + "): " + message
    );
  }
}

ib_conndata_t* buffer_to_conndata(
  ib_conn_t*               conn,
  const IronBee::buffer_t& buffer
)
{
  ib_conndata_t* conndata;
  // We hope IronBee eventually destroys this...
  expect_ok(ib_conn_data_create(conn, &conndata, buffer.length),
    "Allocating connection data."
  );
  conndata->dlen = buffer.length;
  std::copy(
    buffer.data, buffer.data + buffer.length,
    reinterpret_cast<char*>(conndata->data)
  );

  return conndata;
}

}

namespace IronBee {

IronBee::IronBee() :
  m_server {
    IB_SERVER_HEADER_DEFAULTS,
    "cpp_ironbee"
  }
{
  // Trace to stderr.
  ib_trace_init(NULL);

  // Initialize.
  expect_ok(ib_initialize(), "Initializing IronBee.");
  {
    ib_engine_t* engine;
    expect_ok(ib_engine_create(&engine, &m_server), "Creating engine.");
    m_ironbee.reset(engine, &ib_engine_destroy);
  }
  expect_ok(ib_engine_init(m_ironbee.get()), "Initializing engine.");
}

void IronBee::load_config(const std::string& config_path)
{
  boost::shared_ptr<ib_cfgparser_t> parser;

  expect_ok(ib_state_notify_cfg_started(m_ironbee.get()),
    "Starting config."
  );
  {
    ib_cfgparser_t* cp;
    expect_ok(ib_cfgparser_create(&cp, m_ironbee.get()),
      "Creating config parser."
    );
    parser.reset(cp, &ib_cfgparser_destroy);
  }

  expect_ok(ib_cfgparser_parse(parser.get(), config_path.c_str()),
    "Parsing config file."
  );

  ib_state_notify_cfg_finished(m_ironbee.get());

  // Do some sanity checks.
  auto ctx = ib_context_main(m_ironbee.get());
  if (! ctx) {
    throw runtime_error("IronBee has no main context.");
  }
  if (ib_context_get_engine(ctx) != m_ironbee.get()) {
    throw runtime_error("IronBee has corrupt context.");
  }
}

IronBee::connection_p IronBee::open_connection(
  const buffer_t&    local_ip,
  uint16_t           local_port,
  const buffer_t&    remote_ip,
  uint16_t           remote_port
)
{
  return IronBee::connection_p(new Connection(
    *this,
    local_ip,
    local_port,
    remote_ip,
    remote_port
  ));
}

IronBee::connection_p IronBee::open_connection(const input_t& input)
{
  return open_connection(
    input.local_ip,
    input.local_port,
    input.remote_ip,
    input.remote_port
  );
}

IronBee::Connection::Connection(
  IronBee&           ib,
  const buffer_t&    local_ip,
  uint16_t           local_port,
  const buffer_t&    remote_ip,
  uint16_t           remote_port
) :
  m_ib(ib)
{
  expect_ok(ib_conn_create(m_ib.m_ironbee.get(), &m_connection, NULL),
    "Creating connection."
  );

  m_local_ip                 = local_ip.to_s();
  m_remote_ip                = remote_ip.to_s();
  m_connection->local_ipstr  = m_local_ip.c_str();
  m_connection->local_port   = local_port;
  m_connection->remote_ipstr = m_remote_ip.c_str();
  m_connection->remote_port  = remote_port;

  expect_ok(
    ib_state_notify_conn_opened(
      m_ib.m_ironbee.get(),
      m_connection
    ),
    "Opening connection."
  );
}

IronBee::Connection::~Connection()
{
  if (m_connection) {
    close();
  }
}

void IronBee::Connection::close()
{
  expect_ok(
    ib_state_notify_conn_closed(m_ib.m_ironbee.get(), m_connection),
    "Closing connection."
  );
  m_connection = NULL;
}

void IronBee::Connection::data_in(const buffer_t& data)
{
  auto conndata = buffer_to_conndata(
    m_connection,
    data
  );

  expect_ok(
    ib_state_notify_conn_data_in(
        m_ib.m_ironbee.get(),
        conndata
    ),
    "Connection data in."
  );
}

void IronBee::Connection::data_out(const buffer_t& data)
{
  auto conndata = buffer_to_conndata(
    m_connection,
    data
  );

  expect_ok(
    ib_state_notify_conn_data_out(
      m_ib.m_ironbee.get(),
      conndata
    ),
    "Connection data in."
  );
}

} // IronBee
<|endoftext|>


<commit_before>#include "isocalc.h"

#include "fftw3.h"
#include <cassert>
#include <cstring>
#include <complex>
#include <vector>
#include <mutex>

namespace ms {
  namespace detail {
    __attribute ((__destructor__)) void fftwCleanup() { fftw_cleanup(); }

    class FftwArray {
      std::vector<int> dims_;
      std::complex<double>* data_;
      size_t n_;
      public:
      FftwArray(const std::vector<int>& dimensions) : dims_(dimensions) {
        n_ = 1;
        for (int x: dimensions)
          n_ *= x;
        data_ = reinterpret_cast<std::complex<double>*>(fftw_alloc_complex(n_));
        std::memset(data_, 0, n_ * sizeof(fftw_complex));
      }

      fftw_complex* fftw_data() const { return reinterpret_cast<fftw_complex*>(data_); }
      std::complex<double>* data() const { return data_; }
      size_t size() const { return n_; }

      ~FftwArray() {
        fftw_free(data_);
      }
    };
  }

  double monoisotopicMass(const ElementCounter& counter) {
    double sum = 0.0;
    for (auto& item: counter)
      sum += item.second * ms::Element::getByName(item.first).isotope_pattern.masses[0];
    return sum;
  }

  double monoisotopicMass(const std::string& formula) {
    return monoisotopicMass(::sf_parser::parseSumFormula(formula));
  }

  IsotopePattern computeIsotopePattern(const ms::Element& element, size_t amount, double threshold) {
    size_t dim = element.isotope_pattern.size() - 1;
    std::vector<int> dimensions(static_cast<int>(dim), amount + 1);
    detail::FftwArray arr{dimensions};

    static std::mutex plan_mutex; // planning is not thread-safe

    // array setup
    const auto& iso = element.isotope_pattern;
    arr.data()[0] = iso.abundances[0];
    for (size_t i = 0, k = 1; i < dim; i++, k *= amount + 1)
      arr.data()[k] = iso.abundances[dim - i];

    plan_mutex.lock();
    // forward FFT
    auto fwd_plan = fftw_plan_dft(int(dim), &dimensions[0], arr.fftw_data(), arr.fftw_data(),
                                 FFTW_FORWARD, FFTW_ESTIMATE);
    plan_mutex.unlock();
    fftw_execute(fwd_plan);

    // exponentiation
    for (size_t i = 0; i < arr.size(); ++i)
      arr.data()[i] = std::pow(arr.data()[i], amount);
    fftw_destroy_plan(fwd_plan);

    // inverse FFT
    plan_mutex.lock();
    auto bwd_plan = fftw_plan_dft(dim, &dimensions[0], arr.fftw_data(), arr.fftw_data(),
                                  FFTW_BACKWARD, FFTW_ESTIMATE);
    plan_mutex.unlock();
    fftw_execute(bwd_plan);
    for (size_t i = 0; i < arr.size(); ++i)
      arr.data()[i] /= double(arr.size()); // take care of FFTW normalization
    fftw_destroy_plan(bwd_plan);

    ms::IsotopePattern isotope_pattern;

    std::vector<size_t> indices(dim, 0);
    for (size_t i = 0; i < arr.size(); ++i) {
      size_t k;
      size_t n = 0;
      double mass = 0.0;
      for (k = 0; k < dim; ++k) {
        mass += iso.masses[k + 1] * indices[k];
        n += indices[k];
      }

      if (n <= amount && arr.data()[i].real() >= threshold) {
        mass += (amount - n) * iso.masses[0];

        isotope_pattern.masses.push_back(mass);
        isotope_pattern.abundances.push_back(arr.data()[i].real());
      }

      if (i == arr.size() - 1) break;
      for (k = dim - 1; indices[k] == amount; --k);
      indices[k] += 1;
      while (++k < dim) indices[k] = 0;
    }

    isotope_pattern.normalize();
    return isotope_pattern;
  }

  IsotopePattern computeIsotopePattern(const ElementCounter& element_counts,
      double threshold, double fft_threshold)
  {
    assert(threshold < 1);
    ms::IsotopePattern result(0);

    for (auto& item: element_counts) {
      assert(ms::Element::isKnown(item.first));
      auto element = ms::Element::getByName(item.first);
      auto pattern = computeIsotopePattern(element, item.second, fft_threshold);
      result = result.multiply(pattern, threshold * threshold);
    }

    return result;
  }

  IsotopePattern computeIsotopePattern(const std::string& sum_formula,
      double threshold, double fft_threshold)
  {
    auto counts = sf_parser::parseSumFormula(sum_formula);
    return computeIsotopePattern(counts, threshold, fft_threshold);
  }
}

namespace sf_parser {
  typedef ms::ElementCounter ElementCounter;

  using ::sf_parser::ParseError;
  using ::sf_parser::NegativeTotalError;

  class SumFormulaParser {
    std::string s;
    size_t n;
    ElementCounter counter_;
  public:
    SumFormulaParser(const std::string& input) : s(input), n(0) {
      parseSumFormula(counter_);
    }

    const ElementCounter& elementCounts() const {
      return counter_;
    }

  private:
    bool eof() const { return n >= s.length(); }

    void checkAvailable() const {
      if (eof()) throw new ParseError("unexpected end of input", n);
    }

    char nextChar() { checkAvailable(); return s[n++]; }

    char peek() const { checkAvailable(); return s[n]; }

    uint16_t parseOptionalNumber() {
      if (eof() || !std::isdigit(peek()))
        return 1;
      auto pos = n;
      uint16_t result = 0;
      while (!eof() && std::isdigit(peek())) {
        if (result >= 6553)
          throw new ParseError("the number is too big", pos);
        result = result * 10 + (nextChar() - '0');
      }
      return result;
    }

    void parseElement(ElementCounter& counter) {
      std::string element;
      element.push_back(nextChar());
      auto pos = n;
      if (!std::isupper(element.back())) throw new ParseError("expected an element", n);
      while (!eof() && std::islower(peek()))
        element.push_back(nextChar());
      uint16_t num = parseOptionalNumber();
      if (!ms::Element::isKnown(element))
        throw new ParseError("unknown element " + element, pos);
      counter[element] += num;
    }

    void parseSimpleFragment(ElementCounter& counter) {
      while (!eof() && std::isupper(peek())) {
        parseElement(counter);
      }
    }

    void parseFragment(ElementCounter& counter) {
      while (!eof()) {
        if (peek() == '(') {
          nextChar();
          ElementCounter tmp;
          parseFragment(tmp);
          if (nextChar() != ')')
            throw new ParseError("expected closing parenthesis", n - 1);
          auto repeats = parseOptionalNumber();
          for (auto& item: tmp)
            counter[item.first] += item.second * repeats;
        } else if (std::isupper(peek())) {
          parseSimpleFragment(counter);
        } else {
          break;
        }
      }
    }

    void parseMolecularComplex(ElementCounter& counter) {
      ElementCounter tmp;
      auto repeats = parseOptionalNumber();
      while (!eof()) {
        if (peek() == '.' || peek() == '-' || peek() == '+')
          break;
        parseFragment(tmp);
      }
      for (auto& item: tmp)
        counter[item.first] += repeats * item.second;
    }

    void parseSumFormula(ElementCounter& counter) {
      parseMolecularComplex(counter);

      while (!eof()) {
        if (peek() == '.') {
          nextChar();
          parseMolecularComplex(counter);
        } else {
          break;
        }
      }

      if (!eof()) {
        ElementCounter adduct;
        char sign = nextChar();
        int mult;
        if (sign == '-') mult = -1;
        else if (sign == '+') mult = 1;
        else throw new ParseError("expected +/-", n-1);
        parseMolecularComplex(adduct);
        for (auto& item: adduct) {
          auto total = int(counter[item.first]) + mult * int(item.second);
          if (total < 0)
            throw new NegativeTotalError(item.first, total);
          counter[item.first] = total;
        }
      }
    }
  };

  ms::ElementCounter parseSumFormula(const std::string& formula) {
    sf_parser::SumFormulaParser parser{formula};
    return parser.elementCounts();
  }
}
<commit_msg>fftw_destroy_plan is not thread-safe<commit_after>#include "isocalc.h"

#include "fftw3.h"
#include <cassert>
#include <cstring>
#include <complex>
#include <vector>
#include <mutex>

namespace ms {
  namespace detail {
    __attribute ((__destructor__)) void fftwCleanup() { fftw_cleanup(); }

    class FftwArray {
      std::vector<int> dims_;
      std::complex<double>* data_;
      size_t n_;
      public:
      FftwArray(const std::vector<int>& dimensions) : dims_(dimensions) {
        n_ = 1;
        for (int x: dimensions)
          n_ *= x;
        data_ = reinterpret_cast<std::complex<double>*>(fftw_alloc_complex(n_));
        std::memset(data_, 0, n_ * sizeof(fftw_complex));
      }

      fftw_complex* fftw_data() const { return reinterpret_cast<fftw_complex*>(data_); }
      std::complex<double>* data() const { return data_; }
      size_t size() const { return n_; }

      ~FftwArray() {
        fftw_free(data_);
      }
    };
  }

  double monoisotopicMass(const ElementCounter& counter) {
    double sum = 0.0;
    for (auto& item: counter)
      sum += item.second * ms::Element::getByName(item.first).isotope_pattern.masses[0];
    return sum;
  }

  double monoisotopicMass(const std::string& formula) {
    return monoisotopicMass(::sf_parser::parseSumFormula(formula));
  }

  IsotopePattern computeIsotopePattern(const ms::Element& element, size_t amount, double threshold) {
    size_t dim = element.isotope_pattern.size() - 1;
    std::vector<int> dimensions(static_cast<int>(dim), amount + 1);
    detail::FftwArray arr{dimensions};

    static std::mutex plan_mutex; // planning is not thread-safe

    // array setup
    const auto& iso = element.isotope_pattern;
    arr.data()[0] = iso.abundances[0];
    for (size_t i = 0, k = 1; i < dim; i++, k *= amount + 1)
      arr.data()[k] = iso.abundances[dim - i];

    plan_mutex.lock();
    // forward FFT
    auto fwd_plan = fftw_plan_dft(int(dim), &dimensions[0], arr.fftw_data(), arr.fftw_data(),
                                 FFTW_FORWARD, FFTW_ESTIMATE);
    fftw_execute(fwd_plan);

    // exponentiation
    for (size_t i = 0; i < arr.size(); ++i)
      arr.data()[i] = std::pow(arr.data()[i], amount);
    fftw_destroy_plan(fwd_plan);

    // inverse FFT
    auto bwd_plan = fftw_plan_dft(dim, &dimensions[0], arr.fftw_data(), arr.fftw_data(),
                                  FFTW_BACKWARD, FFTW_ESTIMATE);
    fftw_execute(bwd_plan);
    for (size_t i = 0; i < arr.size(); ++i)
      arr.data()[i] /= double(arr.size()); // take care of FFTW normalization
    fftw_destroy_plan(bwd_plan);
    plan_mutex.unlock();

    ms::IsotopePattern isotope_pattern;

    std::vector<size_t> indices(dim, 0);
    for (size_t i = 0; i < arr.size(); ++i) {
      size_t k;
      size_t n = 0;
      double mass = 0.0;
      for (k = 0; k < dim; ++k) {
        mass += iso.masses[k + 1] * indices[k];
        n += indices[k];
      }

      if (n <= amount && arr.data()[i].real() >= threshold) {
        mass += (amount - n) * iso.masses[0];

        isotope_pattern.masses.push_back(mass);
        isotope_pattern.abundances.push_back(arr.data()[i].real());
      }

      if (i == arr.size() - 1) break;
      for (k = dim - 1; indices[k] == amount; --k);
      indices[k] += 1;
      while (++k < dim) indices[k] = 0;
    }

    isotope_pattern.normalize();
    return isotope_pattern;
  }

  IsotopePattern computeIsotopePattern(const ElementCounter& element_counts,
      double threshold, double fft_threshold)
  {
    assert(threshold < 1);
    ms::IsotopePattern result(0);

    for (auto& item: element_counts) {
      assert(ms::Element::isKnown(item.first));
      auto element = ms::Element::getByName(item.first);
      auto pattern = computeIsotopePattern(element, item.second, fft_threshold);
      result = result.multiply(pattern, threshold * threshold);
    }

    return result;
  }

  IsotopePattern computeIsotopePattern(const std::string& sum_formula,
      double threshold, double fft_threshold)
  {
    auto counts = sf_parser::parseSumFormula(sum_formula);
    return computeIsotopePattern(counts, threshold, fft_threshold);
  }
}

namespace sf_parser {
  typedef ms::ElementCounter ElementCounter;

  using ::sf_parser::ParseError;
  using ::sf_parser::NegativeTotalError;

  class SumFormulaParser {
    std::string s;
    size_t n;
    ElementCounter counter_;
  public:
    SumFormulaParser(const std::string& input) : s(input), n(0) {
      parseSumFormula(counter_);
    }

    const ElementCounter& elementCounts() const {
      return counter_;
    }

  private:
    bool eof() const { return n >= s.length(); }

    void checkAvailable() const {
      if (eof()) throw new ParseError("unexpected end of input", n);
    }

    char nextChar() { checkAvailable(); return s[n++]; }

    char peek() const { checkAvailable(); return s[n]; }

    uint16_t parseOptionalNumber() {
      if (eof() || !std::isdigit(peek()))
        return 1;
      auto pos = n;
      uint16_t result = 0;
      while (!eof() && std::isdigit(peek())) {
        if (result >= 6553)
          throw new ParseError("the number is too big", pos);
        result = result * 10 + (nextChar() - '0');
      }
      return result;
    }

    void parseElement(ElementCounter& counter) {
      std::string element;
      element.push_back(nextChar());
      auto pos = n;
      if (!std::isupper(element.back())) throw new ParseError("expected an element", n);
      while (!eof() && std::islower(peek()))
        element.push_back(nextChar());
      uint16_t num = parseOptionalNumber();
      if (!ms::Element::isKnown(element))
        throw new ParseError("unknown element " + element, pos);
      counter[element] += num;
    }

    void parseSimpleFragment(ElementCounter& counter) {
      while (!eof() && std::isupper(peek())) {
        parseElement(counter);
      }
    }

    void parseFragment(ElementCounter& counter) {
      while (!eof()) {
        if (peek() == '(') {
          nextChar();
          ElementCounter tmp;
          parseFragment(tmp);
          if (nextChar() != ')')
            throw new ParseError("expected closing parenthesis", n - 1);
          auto repeats = parseOptionalNumber();
          for (auto& item: tmp)
            counter[item.first] += item.second * repeats;
        } else if (std::isupper(peek())) {
          parseSimpleFragment(counter);
        } else {
          break;
        }
      }
    }

    void parseMolecularComplex(ElementCounter& counter) {
      ElementCounter tmp;
      auto repeats = parseOptionalNumber();
      while (!eof()) {
        if (peek() == '.' || peek() == '-' || peek() == '+')
          break;
        parseFragment(tmp);
      }
      for (auto& item: tmp)
        counter[item.first] += repeats * item.second;
    }

    void parseSumFormula(ElementCounter& counter) {
      parseMolecularComplex(counter);

      while (!eof()) {
        if (peek() == '.') {
          nextChar();
          parseMolecularComplex(counter);
        } else {
          break;
        }
      }

      if (!eof()) {
        ElementCounter adduct;
        char sign = nextChar();
        int mult;
        if (sign == '-') mult = -1;
        else if (sign == '+') mult = 1;
        else throw new ParseError("expected +/-", n-1);
        parseMolecularComplex(adduct);
        for (auto& item: adduct) {
          auto total = int(counter[item.first]) + mult * int(item.second);
          if (total < 0)
            throw new NegativeTotalError(item.first, total);
          counter[item.first] = total;
        }
      }
    }
  };

  ms::ElementCounter parseSumFormula(const std::string& formula) {
    sf_parser::SumFormulaParser parser{formula};
    return parser.elementCounts();
  }
}
<|endoftext|>


<commit_before>#include "OrbitService.h"

#include <iostream>

#include "Capture.h"
#include "ConnectionManager.h"
#include "Core.h"
#include "CoreApp.h"
#include "TcpServer.h"
#include "TimerManager.h"

// TODO: we should probably make it configurable
constexpr uint32_t kAsioServerPort = 44766;

OrbitService::OrbitService() {
  // TODO: these should be a private fields.
  GTimerManager = std::make_unique<TimerManager>();
  GTcpServer = std::make_unique<TcpServer>();
  Capture::Init();

  GTcpServer->StartServer(kAsioServerPort);
  ConnectionManager::Get().InitAsService();

  core_app_ = std::make_unique<CoreApp>();
  GCoreApp = core_app_.get();
  GCoreApp->InitializeManagers();
}

void OrbitService::Run(std::atomic<bool>* exit_requested) {
  while (!(*exit_requested)) {
    GTcpServer->ProcessMainThreadCallbacks();
    Capture::Update();
    Sleep(16);
  }

  GCoreApp = nullptr;
}
<commit_msg>Simple line removals in OrbitService.cpp<commit_after>#include "OrbitService.h"

#include "ConnectionManager.h"
#include "Core.h"
#include "CoreApp.h"
#include "TcpServer.h"

// TODO: we should probably make it configurable
constexpr uint32_t kAsioServerPort = 44766;

OrbitService::OrbitService() {
  // TODO: These should be private fields.
  GTcpServer = std::make_unique<TcpServer>();
  GTcpServer->StartServer(kAsioServerPort);

  ConnectionManager::Get().InitAsService();

  core_app_ = std::make_unique<CoreApp>();
  GCoreApp = core_app_.get();
  GCoreApp->InitializeManagers();
}

void OrbitService::Run(std::atomic<bool>* exit_requested) {
  while (!(*exit_requested)) {
    GTcpServer->ProcessMainThreadCallbacks();
    Sleep(16);
  }

  GCoreApp = nullptr;
}
<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/usr/isteps/istep12/call_omi_io_run_training.C $           */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2020                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
/**
 * @file    call_omi_io_run_training.C
 *
 *  Contains the HWP wrapper for Istep 12.7
 *      exp_omi_train
 *      p10_omi_train
 */
#include    <stdint.h>

#include    <trace/interface.H>
#include    <initservice/taskargs.H>
#include    <errl/errlentry.H>

#include    <isteps/hwpisteperror.H>
#include    <errl/errludtarget.H>

#include    <initservice/isteps_trace.H>
#include    <istepHelperFuncs.H>        // captureError

//Fapi Support
#include    <config.h>
#include    <fapi2.H>
#include    <fapi2/plat_hwp_invoker.H>

//HWP
#include    <exp_omi_train.H>
#include    <p10_omi_train.H>
#include    <chipids.H>                 // for EXPLORER ID

using   namespace   ISTEP;
using   namespace   ISTEP_ERROR;
using   namespace   ERRORLOG;
using   namespace   TARGETING;
using   namespace   ERRORLOG;
using   namespace   ISTEPS_TRACE;

namespace ISTEP_12
{

void* call_omi_io_run_training (void *io_pArgs)
{
    IStepError l_StepError;
    errlHndl_t l_err = nullptr;
    TRACFCOMP( g_trac_isteps_trace, "call_omi_io_run_training entry" );

    do
    {
        // Starting beginning at this istep, we may be unable to scom the OCMBs
        // until the next istep is complete, except in certain cases where the
        // hardware procedure fails. Set ATTR_ATTN_POLL_PLID so ATTN knows to
        // poll the PRD_HWP_PLID before scomming the OCMBs.
        TargetHandle_t sys = nullptr;
        targetService().getTopLevelTarget(sys);
        assert(sys != nullptr);
        sys->setAttr<ATTR_ATTN_POLL_PLID>(1);

        // 12.7.a exp_omi_train.C
        TargetHandleList l_ocmbTargetList;
        getAllChips(l_ocmbTargetList, TYPE_OCMB_CHIP);

        for (const auto & l_ocmb_target : l_ocmbTargetList)
        {
            //  call the HWP with each target
            fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP> l_fapi_ocmb_target
                (l_ocmb_target);

            // Only run exp_omi_train on EXPLORER OCMB targets.
            uint32_t chipId = l_ocmb_target->getAttr< ATTR_CHIP_ID>();
            if (chipId == POWER_CHIPID::EXPLORER_16)
            {
                TRACFCOMP( g_trac_isteps_trace,
                    "Start exp_omi_train on target HUID 0x%.8X",
                    get_huid(l_ocmb_target) );
                FAPI_INVOKE_HWP(l_err, exp_omi_train, l_fapi_ocmb_target);

                //  process return code.
                if ( l_err )
                {
                    TRACFCOMP( g_trac_isteps_trace,
                    "ERROR : call exp_omi_train HWP(): failed on target 0x%08X."
                        TRACE_ERR_FMT,
                        get_huid(l_ocmb_target),
                        TRACE_ERR_ARGS(l_err));

                    // Capture error
                    captureError(l_err, l_StepError, HWPF_COMP_ID,
                                 l_ocmb_target);
                }
                else
                {
                    TRACFCOMP( g_trac_isteps_trace,
                        "SUCCESS :  exp_omi_train HWP on target 0x%.08X",
                        get_huid(l_ocmb_target));
                }
            }
            else
            {
                // Skip exp_omi_train call on non-Explorer chips
                TRACFCOMP( g_trac_isteps_trace,
                    "Skipping exp_omi_train HWP on target HUID 0x%.8X, "
                    "chipId 0x%.4X",
                    get_huid(l_ocmb_target), chipId );
            }
        }

        // Do not continue if an error was encountered
        if(!l_StepError.isNull())
        {
            TRACFCOMP( g_trac_isteps_trace,
                INFO_MRK "call_omi_io_run_training exited early because "
                "exp_omi_train had failures" );
            break;
        }

        // 12.7.b p10_omi_train.C
        TargetHandleList l_omicTargetList;
        getAllChiplets(l_omicTargetList, TYPE_OMIC);

        for (const auto & l_omic_target : l_omicTargetList)
        {
            TRACFCOMP(g_trac_isteps_trace, "p10_omi_train HWP target HUID %.8x",
                get_huid(l_omic_target));

            //  call the HWP with each OMIC target
            fapi2::Target<fapi2::TARGET_TYPE_OMIC>
                l_fapi_omic_target(l_omic_target);

            FAPI_INVOKE_HWP(l_err, p10_omi_train, l_fapi_omic_target );

            //  process return code.
            if ( l_err )
            {
                TRACFCOMP( g_trac_isteps_trace,
                    "ERROR : call p10_omi_train HWP: failed on target 0x%08X. "
                    TRACE_ERR_FMT,
                    get_huid(l_omic_target),
                    TRACE_ERR_ARGS(l_err));

                // Capture error
                captureError(l_err, l_StepError, HWPF_COMP_ID, l_omic_target);
            }
            else
            {
                TRACFCOMP( g_trac_isteps_trace,
                        "SUCCESS :  p10_omi_train HWP on 0x%.08X",
                        get_huid(l_omic_target));
            }
        }
    } while (0);

    TRACFCOMP( g_trac_isteps_trace, "call_omi_io_run_training exit" );

    // end task, returning any errorlogs to IStepDisp
    return l_StepError.getErrorHandle();
}

};
<commit_msg>Swap order of exp_omi_train and p10_omi_train<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/usr/isteps/istep12/call_omi_io_run_training.C $           */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2021                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
/**
 * @file    call_omi_io_run_training.C
 *
 *  Contains the HWP wrapper for Istep 12.7
 *      exp_omi_train
 *      p10_omi_train
 */
#include    <stdint.h>

#include    <trace/interface.H>
#include    <initservice/taskargs.H>
#include    <errl/errlentry.H>

#include    <isteps/hwpisteperror.H>
#include    <errl/errludtarget.H>

#include    <initservice/isteps_trace.H>
#include    <istepHelperFuncs.H>        // captureError

//Fapi Support
#include    <config.h>
#include    <fapi2.H>
#include    <fapi2/plat_hwp_invoker.H>

//HWP
#include    <exp_omi_train.H>
#include    <p10_omi_train.H>
#include    <chipids.H>                 // for EXPLORER ID

using   namespace   ISTEP;
using   namespace   ISTEP_ERROR;
using   namespace   ERRORLOG;
using   namespace   TARGETING;
using   namespace   ERRORLOG;
using   namespace   ISTEPS_TRACE;

namespace ISTEP_12
{

void* call_omi_io_run_training (void *io_pArgs)
{
    IStepError l_StepError;
    errlHndl_t l_err = nullptr;
    TRACFCOMP( g_trac_isteps_trace, "call_omi_io_run_training entry" );

    do
    {
        // Starting beginning at this istep, we may be unable to scom the OCMBs
        // until the next istep is complete, except in certain cases where the
        // hardware procedure fails. Set ATTR_ATTN_POLL_PLID so ATTN knows to
        // poll the PRD_HWP_PLID before scomming the OCMBs.
        TargetHandle_t sys = nullptr;
        targetService().getTopLevelTarget(sys);
        assert(sys != nullptr);
        sys->setAttr<ATTR_ATTN_POLL_PLID>(1);

        // 12.7.a p10_omi_train.C
        TargetHandleList l_omicTargetList;
        getAllChiplets(l_omicTargetList, TYPE_OMIC);

        for (const auto & l_omic_target : l_omicTargetList)
        {
            TRACFCOMP(g_trac_isteps_trace, "p10_omi_train HWP target HUID %.8x",
                get_huid(l_omic_target));

            //  call the HWP with each OMIC target
            fapi2::Target<fapi2::TARGET_TYPE_OMIC>
                l_fapi_omic_target(l_omic_target);

            FAPI_INVOKE_HWP(l_err, p10_omi_train, l_fapi_omic_target );

            //  process return code.
            if ( l_err )
            {
                TRACFCOMP( g_trac_isteps_trace,
                    "ERROR : call p10_omi_train HWP: failed on target 0x%08X. "
                    TRACE_ERR_FMT,
                    get_huid(l_omic_target),
                    TRACE_ERR_ARGS(l_err));

                // Capture error
                captureError(l_err, l_StepError, HWPF_COMP_ID, l_omic_target);
            }
            else
            {
                TRACFCOMP( g_trac_isteps_trace,
                        "SUCCESS :  p10_omi_train HWP on 0x%.08X",
                        get_huid(l_omic_target));
            }
        }

        // Do not continue if an error was encountered
        if(!l_StepError.isNull())
        {
            TRACFCOMP( g_trac_isteps_trace,
                INFO_MRK "call_omi_io_run_training exited early because "
                "p10_omi_train had failures" );
            break;
        }

        // 12.7.b exp_omi_train.C
        TargetHandleList l_ocmbTargetList;
        getAllChips(l_ocmbTargetList, TYPE_OCMB_CHIP);

        for (const auto & l_ocmb_target : l_ocmbTargetList)
        {
            //  call the HWP with each target
            fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP> l_fapi_ocmb_target
                (l_ocmb_target);

            // Only run exp_omi_train on EXPLORER OCMB targets.
            uint32_t chipId = l_ocmb_target->getAttr< ATTR_CHIP_ID>();
            if (chipId == POWER_CHIPID::EXPLORER_16)
            {
                TRACFCOMP( g_trac_isteps_trace,
                    "Start exp_omi_train on target HUID 0x%.8X",
                    get_huid(l_ocmb_target) );
                FAPI_INVOKE_HWP(l_err, exp_omi_train, l_fapi_ocmb_target);

                //  process return code.
                if ( l_err )
                {
                    TRACFCOMP( g_trac_isteps_trace,
                    "ERROR : call exp_omi_train HWP(): failed on target 0x%08X."
                        TRACE_ERR_FMT,
                        get_huid(l_ocmb_target),
                        TRACE_ERR_ARGS(l_err));

                    // Capture error
                    captureError(l_err, l_StepError, HWPF_COMP_ID,
                                 l_ocmb_target);
                }
                else
                {
                    TRACFCOMP( g_trac_isteps_trace,
                        "SUCCESS :  exp_omi_train HWP on target 0x%.08X",
                        get_huid(l_ocmb_target));
                }
            }
            else
            {
                // Skip exp_omi_train call on non-Explorer chips
                TRACFCOMP( g_trac_isteps_trace,
                    "Skipping exp_omi_train HWP on target HUID 0x%.8X, "
                    "chipId 0x%.4X",
                    get_huid(l_ocmb_target), chipId );
            }
        }

    } while (0);

    TRACFCOMP( g_trac_isteps_trace, "call_omi_io_run_training exit" );

    // end task, returning any errorlogs to IStepDisp
    return l_StepError.getErrorHandle();
}

};
<|endoftext|>