<commit_before>// Jubatus: Online machine learning framework for distributed environment
// Copyright (C) 2011,2012 Preferred Infrastructure and Nippon Telegraph and Telephone Corporation.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License version 2.1 as published by the Free Software Foundation.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

#ifndef JUBATUS_SERVER_FRAMEWORK_SERVER_HELPER_HPP_
#define JUBATUS_SERVER_FRAMEWORK_SERVER_HELPER_HPP_

#include <sys/types.h>
#include <unistd.h>

#include <map>
#include <string>
#include <glog/logging.h>
#include "jubatus/util/lang/bind.h"
#include "jubatus/util/lang/shared_ptr.h"
#include "jubatus/util/system/sysstat.h"
#include "jubatus/util/system/time_util.h"

#include "jubatus/core/common/jsonconfig.hpp"
#include "mixer/mixer.hpp"
#include "server_util.hpp"
#include "../../config.hpp"
#include "../common/lock_service.hpp"
#include "../common/mprpc/rpc_server.hpp"
#include "../common/signals.hpp"
#include "../common/config.hpp"

using jubatus::util::system::time::clock_time;
using jubatus::util::system::time::get_clock_time;

namespace jubatus {
namespace server {
namespace framework {

class server_helper_impl {
 public:
  explicit server_helper_impl(const server_argv& a);
  ~server_helper_impl();

  void prepare_for_start(const server_argv& a, bool use_cht);
  void prepare_for_run(const server_argv& a, bool use_cht);
  void get_config_lock(const server_argv& a, int retry);

  jubatus::util::lang::shared_ptr<common::lock_service> zk() const {
    return zk_;
  }

 private:
  jubatus::util::lang::shared_ptr<common::lock_service> zk_;
  jubatus::util::lang::shared_ptr<common::try_lockable> zk_config_lock_;
};

template<typename Server>
class server_helper {
 public:
  typedef typename Server::status_t status_t;

  explicit server_helper(const server_argv& a, bool use_cht = false)
      : impl_(a),
        start_time_(get_clock_time()),
        use_cht_(use_cht) {
    impl_.prepare_for_start(a, use_cht);
    server_.reset(new Server(a, impl_.zk()));

    impl_.get_config_lock(a, 3);

    try {
      server_->set_config(get_conf(a));
    } catch (const core::common::jsonconfig::cast_check_error& e) {
      core::common::config_exception config_error;
      const core::common::jsonconfig::config_error_list& errors = e.errors();
      for (core::common::jsonconfig::config_error_list::const_iterator
          it = errors.begin(), end = errors.end(); it != end; ++it) {
        config_error << core::common::exception::error_message((*it)->what());
      }
      // send error message to caller
      throw JUBATUS_EXCEPTION(config_error);
    } catch (const jubatus::util::lang::parse_error& e) {
      // exit immediately on JSON parse error with exit-code 1
      std::string msg =
          std::string("syntax error in configuration: ") +
          (a.is_standalone() ?
           a.configpath :
           std::string("<zookeeper>")) + ":" +
          jubatus::util::lang::lexical_cast<std::string>(e.lineno()) + ":" +
          jubatus::util::lang::lexical_cast<std::string>(e.pos()) + " " +
          e.msg();

      LOG(ERROR) << msg;
      exit(1);
    }

    try {
      // standalone only, is it desirable?
      if (a.is_standalone() && !a.modelpath.empty()) {
        server_->load_file(a.modelpath);
      }
    } catch (const std::runtime_error& e) {
      exit(1);
    }
  }

  std::map<std::string, std::string> get_loads() const {
    std::map<std::string, std::string> result;
    {
      jubatus::util::system::sysstat::sysstat_ret sys;
      get_sysstat(sys);
      result["loadavg"] =
          jubatus::util::lang::lexical_cast<std::string>(sys.loadavg);
      result["total_memory"] = jubatus::util::lang::lexical_cast<std::string>(
          sys.total_memory);
      result["free_memory"] = jubatus::util::lang::lexical_cast<std::string>(
          sys.free_memory);
    }
    return result;
  }

  std::map<std::string, status_t> get_status() const {
    std::map<std::string, status_t> status;
    const server_argv& a = server_->argv();
    status_t& data = status[get_server_identifier(a)];

    clock_time ct = get_clock_time();
    data["clock_time"] =
       jubatus::util::lang::lexical_cast<std::string>(ct.sec);
    data["start_time"] =
       jubatus::util::lang::lexical_cast<std::string>(start_time_.sec);
    data["uptime"] =
       jubatus::util::lang::lexical_cast<std::string>(ct - start_time_);

    common::machine_status_t mt;
    common::get_machine_status(mt);
    data["VIRT"] =
        jubatus::util::lang::lexical_cast<std::string>(mt.vm_size);
    data["RSS"] =
        jubatus::util::lang::lexical_cast<std::string>(mt.vm_resident);
    data["SHR"] =
        jubatus::util::lang::lexical_cast<std::string>(mt.vm_share);

    data["timeout"] = jubatus::util::lang::lexical_cast<std::string>(a.timeout);
    data["threadnum"] =
        jubatus::util::lang::lexical_cast<std::string>(a.threadnum);
    data["datadir"] = a.datadir;
    data["is_standalone"] = jubatus::util::lang::lexical_cast<std::string>(
        a.is_standalone());
    data["VERSION"] = JUBATUS_VERSION;
    data["PROGNAME"] = a.program_name;
    data["type"] = a.type;
    data["logdir"] = a.logdir.empty() ? "/dev/stderr" : a.logdir;
    data["loglevel"] = google::GetLogSeverityName(a.loglevel);

    std::string configpath;
    if (a.is_standalone()) {
        configpath = a.configpath;
    } else {
        // return zookeeper node name
        jubatus::server::common::build_config_path(configpath, a.type, a.name);
    }
    data["configpath"] = configpath;

    data["pid"] =
        jubatus::util::lang::lexical_cast<std::string>(getpid());
    data["user"] = jubatus::server::common::get_user_name();

    data["update_count"] = jubatus::util::lang::lexical_cast<std::string>(
        server_->update_count());

    data["last_saved"] =
        jubatus::util::lang::lexical_cast<std::string>
        (server_->last_saved_sec());
    data["last_saved_path"] = server_->last_saved_path();
    data["last_loaded"] =
        jubatus::util::lang::lexical_cast<std::string>
        (server_->last_loaded_sec());
    data["last_loaded_path"] = server_->last_loaded_path();

    server_->get_status(data);

    // distributed mode only
    if (!a.is_standalone()) {
        data["zk"] = a.z;
        data["name"] = a.name;
        data["interval_sec"] =
            jubatus::util::lang::lexical_cast<std::string>(a.interval_sec);
        data["interval_count"] = jubatus::util::lang::lexical_cast<std::string>(
            a.interval_count);
        data["zookeeper_timeout"] =
            jubatus::util::lang::lexical_cast<std::string>(a.zookeeper_timeout);
        data["interconnect_timeout"] =
            jubatus::util::lang::lexical_cast<std::string>
            (a.interconnect_timeout);
        data["connected_zookeeper"] = impl_.zk()->get_connected_host_and_port();

        std::stringstream use_cht;
        use_cht << std::boolalpha << use_cht_;
        data["use_cht"] = use_cht.str();

        data["mixer"] = a.mixer;
        server_->get_mixer()->get_status(data);
    }

    return status;
  }

  int start(common::mprpc::rpc_server& serv) {
    const server_argv& a = server_->argv();

    if (!a.is_standalone()) {
      server_->get_mixer()->start();
    }

    try {
      serv.listen(a.port, a.bind_address);
      LOG(INFO) << "start listening at port " << a.port;

      serv.start(a.threadnum, true);

      // RPC server started, then register group membership
      impl_.prepare_for_run(a, use_cht_);
      LOG(INFO) << common::get_program_name() << " RPC server startup";

      // Stop RPC server when terminate signal is sent
      common::set_action_on_term(
          jubatus::util::lang::bind(
              &server_helper::stop, this, jubatus::util::lang::ref(serv)));

      start_time_ = get_clock_time();

      // wait for termination
      serv.join();

      // RPC server stopped, then stop mixer
      if (!a.is_standalone()) {
        server_->get_mixer()->stop();
      }

      return 0;
    } catch (const mp::system_error& e) {
      if (e.code == EADDRINUSE) {
        LOG(FATAL) << "server failed to start: any process using port "
            << a.port << "?";
      } else {
        LOG(FATAL) << "server failed to start: " << e.what();
      }
    } catch (jubatus::core::common::exception::jubatus_exception&) {
      throw;
    } catch (const std::exception& e) {
      LOG(FATAL) << "server failed to start: " << e.what();
    }
    return -1;
  }

  void stop(common::mprpc::rpc_server& serv) {
    LOG(INFO) << "stopping RPC server";
    serv.end();
  }

  jubatus::util::lang::shared_ptr<Server> server() const {
    return server_;
  }

  jubatus::util::concurrent::rw_mutex& rw_mutex() {
    return server_->rw_mutex();
  }

 private:
  jubatus::util::lang::shared_ptr<Server> server_;
  server_helper_impl impl_;
  clock_time start_time_;
  const bool use_cht_;
};

}  // namespace framework
}  // namespace server
}  // namespace jubatus

#define JRLOCK_(p) \
  ::jubatus::util::concurrent::scoped_rlock lk((p)->rw_mutex())

#define JWLOCK_(p) \
  ::jubatus::util::concurrent::scoped_wlock lk((p)->rw_mutex()); \
  (p)->server()->event_model_updated()

#define NOLOCK_(p)

#endif  // JUBATUS_SERVER_FRAMEWORK_SERVER_HELPER_HPP_
<commit_msg>Not use boolalpha in use_cht<commit_after>// Jubatus: Online machine learning framework for distributed environment
// Copyright (C) 2011,2012 Preferred Infrastructure and Nippon Telegraph and Telephone Corporation.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License version 2.1 as published by the Free Software Foundation.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

#ifndef JUBATUS_SERVER_FRAMEWORK_SERVER_HELPER_HPP_
#define JUBATUS_SERVER_FRAMEWORK_SERVER_HELPER_HPP_

#include <sys/types.h>
#include <unistd.h>

#include <map>
#include <string>
#include <glog/logging.h>
#include "jubatus/util/lang/bind.h"
#include "jubatus/util/lang/shared_ptr.h"
#include "jubatus/util/system/sysstat.h"
#include "jubatus/util/system/time_util.h"

#include "jubatus/core/common/jsonconfig.hpp"
#include "mixer/mixer.hpp"
#include "server_util.hpp"
#include "../../config.hpp"
#include "../common/lock_service.hpp"
#include "../common/mprpc/rpc_server.hpp"
#include "../common/signals.hpp"
#include "../common/config.hpp"

using jubatus::util::system::time::clock_time;
using jubatus::util::system::time::get_clock_time;

namespace jubatus {
namespace server {
namespace framework {

class server_helper_impl {
 public:
  explicit server_helper_impl(const server_argv& a);
  ~server_helper_impl();

  void prepare_for_start(const server_argv& a, bool use_cht);
  void prepare_for_run(const server_argv& a, bool use_cht);
  void get_config_lock(const server_argv& a, int retry);

  jubatus::util::lang::shared_ptr<common::lock_service> zk() const {
    return zk_;
  }

 private:
  jubatus::util::lang::shared_ptr<common::lock_service> zk_;
  jubatus::util::lang::shared_ptr<common::try_lockable> zk_config_lock_;
};

template<typename Server>
class server_helper {
 public:
  typedef typename Server::status_t status_t;

  explicit server_helper(const server_argv& a, bool use_cht = false)
      : impl_(a),
        start_time_(get_clock_time()),
        use_cht_(use_cht) {
    impl_.prepare_for_start(a, use_cht);
    server_.reset(new Server(a, impl_.zk()));

    impl_.get_config_lock(a, 3);

    try {
      server_->set_config(get_conf(a));
    } catch (const core::common::jsonconfig::cast_check_error& e) {
      core::common::config_exception config_error;
      const core::common::jsonconfig::config_error_list& errors = e.errors();
      for (core::common::jsonconfig::config_error_list::const_iterator
          it = errors.begin(), end = errors.end(); it != end; ++it) {
        config_error << core::common::exception::error_message((*it)->what());
      }
      // send error message to caller
      throw JUBATUS_EXCEPTION(config_error);
    } catch (const jubatus::util::lang::parse_error& e) {
      // exit immediately on JSON parse error with exit-code 1
      std::string msg =
          std::string("syntax error in configuration: ") +
          (a.is_standalone() ?
           a.configpath :
           std::string("<zookeeper>")) + ":" +
          jubatus::util::lang::lexical_cast<std::string>(e.lineno()) + ":" +
          jubatus::util::lang::lexical_cast<std::string>(e.pos()) + " " +
          e.msg();

      LOG(ERROR) << msg;
      exit(1);
    }

    try {
      // standalone only, is it desirable?
      if (a.is_standalone() && !a.modelpath.empty()) {
        server_->load_file(a.modelpath);
      }
    } catch (const std::runtime_error& e) {
      exit(1);
    }
  }

  std::map<std::string, std::string> get_loads() const {
    std::map<std::string, std::string> result;
    {
      jubatus::util::system::sysstat::sysstat_ret sys;
      get_sysstat(sys);
      result["loadavg"] =
          jubatus::util::lang::lexical_cast<std::string>(sys.loadavg);
      result["total_memory"] = jubatus::util::lang::lexical_cast<std::string>(
          sys.total_memory);
      result["free_memory"] = jubatus::util::lang::lexical_cast<std::string>(
          sys.free_memory);
    }
    return result;
  }

  std::map<std::string, status_t> get_status() const {
    std::map<std::string, status_t> status;
    const server_argv& a = server_->argv();
    status_t& data = status[get_server_identifier(a)];

    clock_time ct = get_clock_time();
    data["clock_time"] =
       jubatus::util::lang::lexical_cast<std::string>(ct.sec);
    data["start_time"] =
       jubatus::util::lang::lexical_cast<std::string>(start_time_.sec);
    data["uptime"] =
       jubatus::util::lang::lexical_cast<std::string>(ct - start_time_);

    common::machine_status_t mt;
    common::get_machine_status(mt);
    data["VIRT"] =
        jubatus::util::lang::lexical_cast<std::string>(mt.vm_size);
    data["RSS"] =
        jubatus::util::lang::lexical_cast<std::string>(mt.vm_resident);
    data["SHR"] =
        jubatus::util::lang::lexical_cast<std::string>(mt.vm_share);

    data["timeout"] = jubatus::util::lang::lexical_cast<std::string>(a.timeout);
    data["threadnum"] =
        jubatus::util::lang::lexical_cast<std::string>(a.threadnum);
    data["datadir"] = a.datadir;
    data["is_standalone"] = jubatus::util::lang::lexical_cast<std::string>(
        a.is_standalone());
    data["VERSION"] = JUBATUS_VERSION;
    data["PROGNAME"] = a.program_name;
    data["type"] = a.type;
    data["logdir"] = a.logdir.empty() ? "/dev/stderr" : a.logdir;
    data["loglevel"] = google::GetLogSeverityName(a.loglevel);

    std::string configpath;
    if (a.is_standalone()) {
        configpath = a.configpath;
    } else {
        // return zookeeper node name
        jubatus::server::common::build_config_path(configpath, a.type, a.name);
    }
    data["configpath"] = configpath;

    data["pid"] =
        jubatus::util::lang::lexical_cast<std::string>(getpid());
    data["user"] = jubatus::server::common::get_user_name();

    data["update_count"] = jubatus::util::lang::lexical_cast<std::string>(
        server_->update_count());

    data["last_saved"] =
        jubatus::util::lang::lexical_cast<std::string>
        (server_->last_saved_sec());
    data["last_saved_path"] = server_->last_saved_path();
    data["last_loaded"] =
        jubatus::util::lang::lexical_cast<std::string>
        (server_->last_loaded_sec());
    data["last_loaded_path"] = server_->last_loaded_path();

    server_->get_status(data);

    // distributed mode only
    if (!a.is_standalone()) {
        data["zk"] = a.z;
        data["name"] = a.name;
        data["interval_sec"] =
            jubatus::util::lang::lexical_cast<std::string>(a.interval_sec);
        data["interval_count"] = jubatus::util::lang::lexical_cast<std::string>(
            a.interval_count);
        data["zookeeper_timeout"] =
            jubatus::util::lang::lexical_cast<std::string>(a.zookeeper_timeout);
        data["interconnect_timeout"] =
            jubatus::util::lang::lexical_cast<std::string>
            (a.interconnect_timeout);
        data["connected_zookeeper"] = impl_.zk()->get_connected_host_and_port();
        data["use_cht"] = jubatus::util::lang::lexical_cast<std::string>(
            use_cht_);

        data["mixer"] = a.mixer;
        server_->get_mixer()->get_status(data);
    }

    return status;
  }

  int start(common::mprpc::rpc_server& serv) {
    const server_argv& a = server_->argv();

    if (!a.is_standalone()) {
      server_->get_mixer()->start();
    }

    try {
      serv.listen(a.port, a.bind_address);
      LOG(INFO) << "start listening at port " << a.port;

      serv.start(a.threadnum, true);

      // RPC server started, then register group membership
      impl_.prepare_for_run(a, use_cht_);
      LOG(INFO) << common::get_program_name() << " RPC server startup";

      // Stop RPC server when terminate signal is sent
      common::set_action_on_term(
          jubatus::util::lang::bind(
              &server_helper::stop, this, jubatus::util::lang::ref(serv)));

      start_time_ = get_clock_time();

      // wait for termination
      serv.join();

      // RPC server stopped, then stop mixer
      if (!a.is_standalone()) {
        server_->get_mixer()->stop();
      }

      return 0;
    } catch (const mp::system_error& e) {
      if (e.code == EADDRINUSE) {
        LOG(FATAL) << "server failed to start: any process using port "
            << a.port << "?";
      } else {
        LOG(FATAL) << "server failed to start: " << e.what();
      }
    } catch (jubatus::core::common::exception::jubatus_exception&) {
      throw;
    } catch (const std::exception& e) {
      LOG(FATAL) << "server failed to start: " << e.what();
    }
    return -1;
  }

  void stop(common::mprpc::rpc_server& serv) {
    LOG(INFO) << "stopping RPC server";
    serv.end();
  }

  jubatus::util::lang::shared_ptr<Server> server() const {
    return server_;
  }

  jubatus::util::concurrent::rw_mutex& rw_mutex() {
    return server_->rw_mutex();
  }

 private:
  jubatus::util::lang::shared_ptr<Server> server_;
  server_helper_impl impl_;
  clock_time start_time_;
  const bool use_cht_;
};

}  // namespace framework
}  // namespace server
}  // namespace jubatus

#define JRLOCK_(p) \
  ::jubatus::util::concurrent::scoped_rlock lk((p)->rw_mutex())

#define JWLOCK_(p) \
  ::jubatus::util::concurrent::scoped_wlock lk((p)->rw_mutex()); \
  (p)->server()->event_model_updated()

#define NOLOCK_(p)

#endif  // JUBATUS_SERVER_FRAMEWORK_SERVER_HELPER_HPP_
<|endoftext|>


<commit_before>#ifndef GNR_FORWARDER_HPP
# define GNR_FORWARDER_HPP
# pragma once

// std::size_t
#include <cstddef>

#include <functional>

#include <type_traits>

#include <utility>

namespace gnr
{

namespace detail::forwarder
{

enum : std::size_t { default_size = 4 * sizeof(void*) };

template <typename, std::size_t, bool>
class forwarder_impl2;

template <typename R, typename ...A, std::size_t N, bool E>
class forwarder_impl2<R (A...), N, E>
{
protected:
  R (*stub_)(void*, A&&...) noexcept(E) {};

  std::aligned_storage_t<N> store_;

  template <typename F>
  static constexpr auto is_invocable() noexcept
  {
    return std::is_invocable_r_v<R, F, A...>;
  }

public:
  using result_type = R;

public:
  R operator()(A... args) const noexcept(E)
  {
    //assert(stub_);
    return stub_(std::addressof(store_), std::forward<A>(args)...);
  }

  template <typename F,
    typename = std::enable_if_t<std::is_invocable_r_v<R, F, A...>>
  >
  void assign(F&& f) noexcept(noexcept(std::decay_t<F>(std::forward<F>(f))))
  {
    using functor_type = std::decay_t<F>;

    static_assert(sizeof(functor_type) <= sizeof(store_),
      "functor too large");
    static_assert(std::is_trivially_copyable<functor_type>{},
      "functor not trivially copyable");

    ::new (std::addressof(store_)) functor_type(std::forward<F>(f));

    stub_ = [](void const* const ptr, A&&... args) noexcept(E) -> R
    {
      return std::invoke(*static_cast<functor_type*>(const_cast<void*>(ptr)),
        std::forward<A>(args)...);
    };
  }
};

template <typename, std::size_t>
class forwarder_impl;

template <typename R, typename ...A, std::size_t N>
class forwarder_impl<R (A...), N> :
  public forwarder_impl2<R (A...), N, false>
{
};

template <typename R, typename ...A, std::size_t N>
class forwarder_impl<R (A...) noexcept, N> :
  public forwarder_impl2<R (A...), N, true>
{
};

}

template <typename A, std::size_t N = detail::forwarder::default_size>
class forwarder : public detail::forwarder::forwarder_impl<A, N>
{
  using inherited_t = detail::forwarder::forwarder_impl<A, N>;

public:
  enum : std::size_t { size = N };

  forwarder() = default;

  forwarder(forwarder const&) = default;

  forwarder(forwarder&&) = default;

  template <typename F,
    typename = std::enable_if_t<
      !std::is_same_v<std::decay_t<F>, forwarder> &&
      inherited_t::template is_invocable<F>()
    >
  >
  forwarder(F&& f) noexcept(noexcept(inherited_t::assign(std::forward<F>(f))))
  {
    inherited_t::assign(std::forward<F>(f));
  }

  forwarder& operator=(forwarder const&) = default;

  forwarder& operator=(forwarder&&) = default;

  auto& operator=(std::nullptr_t) noexcept
  {
    return reset(), *this;
  }

  template <typename F>
  forwarder& operator=(F&& f) noexcept(
    noexcept(inherited_t::assign(std::forward<F>(f))))
  {
    static_assert(inherited_t::template is_invocable<F>());
    return inherited_t::assign(std::forward<F>(f)), *this;
  }

  explicit operator bool() const noexcept
  {
    return inherited_t::stub_;
  }

  bool operator==(std::nullptr_t) noexcept
  {
    return *this;
  }

  bool operator!=(std::nullptr_t) noexcept
  {
    return !operator==(nullptr);
  }

  void assign(std::nullptr_t) noexcept
  {
    reset();
  }

  void reset() noexcept
  {
    inherited_t::stub_ = {};
  }

  void swap(forwarder& other) noexcept
  {
    std::swap(*this, other);
  }

  void swap(forwarder&& other) noexcept
  {
    std::swap(*this, std::move(other));
  }

  template <typename T>
  auto target() noexcept
  {
    return reinterpret_cast<T*>(std::addressof(inherited_t::store_));
  }

  template <typename T>
  auto target() const noexcept
  {
    return reinterpret_cast<T const*>(std::addressof(inherited_t::store_));
  }
};

}

#endif // GNR_FORWARDER_HPP
<commit_msg>some fixes<commit_after>#ifndef GNR_FORWARDER_HPP
# define GNR_FORWARDER_HPP
# pragma once

// std::size_t
#include <cstddef>

#include <functional>

#include <type_traits>

#include <utility>

namespace gnr
{

namespace detail::forwarder
{

enum : std::size_t { default_size = 4 * sizeof(void*) };

template <typename, std::size_t, bool>
class forwarder_impl2;

template <typename R, typename ...A, std::size_t N, bool E>
class forwarder_impl2<R (A...), N, E>
{
protected:
  R (*stub_)(void*, A&&...) noexcept(E) {};

  std::aligned_storage_t<N> store_;

  template <typename F>
  static constexpr auto is_invocable() noexcept
  {
    return std::is_invocable_r_v<R, F, A...>;
  }

public:
  using result_type = R;

public:
  R operator()(A... args) const noexcept(E)
  {
    //assert(stub_);
    return stub_(std::addressof(store_), std::forward<A>(args)...);
  }

  template <typename F,
    typename = std::enable_if_t<std::is_invocable_r_v<R, F, A...>>
  >
  void assign(F&& f) noexcept(noexcept(std::decay_t<F>(std::forward<F>(f))))
  {
    using functor_type = std::decay_t<F>;
    static_assert(sizeof(functor_type) <= sizeof(store_),
      "functor too large");
    static_assert(std::is_trivially_copyable<functor_type>{},
      "functor not trivially copyable");

    ::new (std::addressof(store_)) functor_type(std::forward<F>(f));

    stub_ = [](void const* const ptr, A&&... args) noexcept(E) -> R
      {
        return std::invoke(
          *static_cast<functor_type*>(const_cast<void*>(ptr)),
          std::forward<A>(args)...);
      };
  }
};

template <typename, std::size_t>
class forwarder_impl;

template <typename R, typename ...A, std::size_t N>
class forwarder_impl<R (A...), N> :
  public forwarder_impl2<R (A...), N, false>
{
};

template <typename R, typename ...A, std::size_t N>
class forwarder_impl<R (A...) noexcept, N> :
  public forwarder_impl2<R (A...), N, true>
{
};

}

template <typename A, std::size_t N = detail::forwarder::default_size>
class forwarder : public detail::forwarder::forwarder_impl<A, N>
{
  using inherited_t = detail::forwarder::forwarder_impl<A, N>;

public:
  enum : std::size_t { size = N };

  forwarder() = default;

  forwarder(forwarder const&) = default;

  forwarder(forwarder&&) = default;

  template <typename F,
    typename = std::enable_if_t<
      !std::is_same_v<std::decay_t<F>, forwarder> &&
      inherited_t::template is_invocable<F>()
    >
  >
  forwarder(F&& f) noexcept(noexcept(inherited_t::assign(std::forward<F>(f))))
  {
    inherited_t::assign(std::forward<F>(f));
  }

  forwarder& operator=(forwarder const&) = default;

  forwarder& operator=(forwarder&&) = default;

  auto& operator=(std::nullptr_t) noexcept
  {
    return reset(), *this;
  }

  template <typename F>
  forwarder& operator=(F&& f) noexcept(
    noexcept(inherited_t::assign(std::forward<F>(f))))
  {
    static_assert(inherited_t::template is_invocable<F>());
    return inherited_t::assign(std::forward<F>(f)), *this;
  }

  explicit operator bool() const noexcept
  {
    return inherited_t::stub_;
  }

  bool operator==(std::nullptr_t) noexcept
  {
    return *this;
  }

  bool operator!=(std::nullptr_t) noexcept
  {
    return !operator==(nullptr);
  }

  void assign(std::nullptr_t) noexcept
  {
    reset();
  }

  void reset() noexcept
  {
    inherited_t::stub_ = {};
  }

  void swap(forwarder& other) noexcept
  {
    std::swap(*this, other);
  }

  void swap(forwarder&& other) noexcept
  {
    std::swap(*this, std::move(other));
  }

  template <typename T>
  auto target() noexcept
  {
    return reinterpret_cast<T*>(std::addressof(inherited_t::store_));
  }

  template <typename T>
  auto target() const noexcept
  {
    return reinterpret_cast<T const*>(std::addressof(inherited_t::store_));
  }
};

}

#endif // GNR_FORWARDER_HPP
<|endoftext|>


<commit_before>/* Copyright (C) 2005-2008 Damien Stehle.
   Copyright (C) 2007 David Cade.
   Copyright (C) 2011 Xavier Pujol.

   This file is part of fplll. fplll 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.

   fplll 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 fplll. If not, see <http://www.gnu.org/licenses/>. */

/* Template source file */

#include "lll.h"
#include "util.h"

FPLLL_BEGIN_NAMESPACE

static inline bool is_power_of_2(int i) { return (i & (i - 1)) == 0; }

template <class ZT, class FT>
LLLReduction<ZT, FT>::LLLReduction(MatGSOInterface<ZT, FT> &m, double delta, double eta, int flags)
    : status(RED_SUCCESS), final_kappa(0), last_early_red(0), n_swaps(0), m(m)
{
  /* No early reduction in proved mode (i.e. enable_int_gram=true).
     NOTE: To make this possible, the hypothesis "g(i, j) is valid if
     0 <= i < n_known_rows and j <= i" in gso.h should be changed and
     MatGSOInterface<ZT, FT>::discover_row() should be rewritten. */
  enable_early_red = (flags & LLL_EARLY_RED) && !m.enable_int_gram;
  siegel           = flags & LLL_SIEGEL;
  verbose          = flags & LLL_VERBOSE;
  this->delta      = delta;
  this->eta        = eta;
  swap_threshold   = siegel ? delta - eta * eta : delta;
  zeros            = 0;
}

template <class ZT, class FT>
bool LLLReduction<ZT, FT>::lll(int kappa_min, int kappa_start, int kappa_end,
                               int size_reduction_start)
{
  if (kappa_end == -1)
    kappa_end = m.d;

  FPLLL_DEBUG_CHECK(kappa_min <= kappa_start && kappa_start < kappa_end && kappa_end <= m.d);
  int start_time = cputime();
  int kappa      = kappa_start + 1;
  int kappa_max  = 0;
  int d          = kappa_end - kappa_min;

  zeros       = 0;
  n_swaps     = 0;
  final_kappa = 0;
  if (verbose)
    print_params();
  extend_vect(lovasz_tests, kappa_end);
  extend_vect(babai_mu, kappa_end);
  extend_vect(babai_expo, kappa_end);

  for (; zeros < d && m.b_row_is_zero(0); zeros++)
  {
    m.move_row(kappa_min, kappa_end - 1 - zeros);
  }

  if (zeros < d && ((kappa_start > 0 && !babai(kappa_start, kappa_start, size_reduction_start)) ||
                    !m.update_gso_row(kappa_start)))
  {
    final_kappa = kappa_start;
    return false;
  }

  long long iter, max_iter;
  max_iter = static_cast<long long>(
      d - 2 * d * (d + 1) * ((m.get_max_exp_of_b() + 3) / std::log(delta.get_d())));

  for (iter = 0; iter < max_iter && kappa < kappa_end - zeros; iter++)
  {
    if (kappa > kappa_max)
    {
      if (verbose)
      {
        cerr << "Discovering vector " << kappa - kappa_min + 1 + zeros << "/" << d
             << " cputime=" << cputime() - start_time << endl;
      }
      kappa_max = kappa;
      if (enable_early_red && is_power_of_2(kappa) && kappa > last_early_red)
      {
        if (!early_reduction(kappa, size_reduction_start))
        {
          final_kappa = kappa;
          return false;
        }
      }
    }

    // Lazy size reduction
    if (!babai(kappa, kappa, size_reduction_start))
    {
      final_kappa = kappa;
      return false;
    }

    // Tests Lovasz's condition
    m.get_gram(lovasz_tests[0], kappa, kappa);
    for (int i = 1; i <= kappa; i++)
    {
      ftmp1.mul(m.get_mu_exp(kappa, i - 1), m.get_r_exp(kappa, i - 1));
      lovasz_tests[i].sub(lovasz_tests[i - 1], ftmp1);
    }
    ftmp1.mul(m.get_r_exp(kappa - 1, kappa - 1), swap_threshold);
    if (m.enable_row_expo)
    {
      ftmp1.mul_2si(ftmp1, 2 * (m.row_expo[kappa - 1] - m.row_expo[kappa]));
    }

    if (ftmp1 > lovasz_tests[siegel ? kappa : kappa - 1])
    {
      n_swaps++;
      // Failure, computes the insertion index
      int old_k = kappa;
      for (kappa--; kappa > kappa_min; kappa--)
      {
        ftmp1.mul(m.get_r_exp(kappa - 1, kappa - 1), swap_threshold);
        if (m.enable_row_expo)
        {
          ftmp1.mul_2si(ftmp1, 2 * (m.row_expo[kappa - 1] - m.row_expo[old_k]));
        }
        if (ftmp1 < lovasz_tests[siegel ? kappa : kappa - 1])
          break;
      }
      // FPLLL_TRACE("Lovasz's condition is not satisfied, kappa=" << kappa << " old_kappa=" <<
      // old_k);
      // Moves the vector
      if (lovasz_tests[kappa] > 0)
      {
        m.move_row(old_k, kappa);
      }
      else
      {
        zeros++;
        m.move_row(old_k, kappa_end - zeros);
        kappa = old_k;
        continue;
      }
    }

    m.set_r(kappa, kappa, lovasz_tests[kappa]);
    kappa++;
  }

  if (kappa < kappa_end - zeros)
    return set_status(RED_LLL_FAILURE);
  else
    return set_status(RED_SUCCESS);
}

template <class ZT, class FT>
bool LLLReduction<ZT, FT>::babai(int kappa, int size_reduction_end, int size_reduction_start)
{
  // FPLLL_TRACE_IN("kappa=" << kappa);
  long max_expo = LONG_MAX;

  for (int iter = 0;; iter++)
  {
    if (!m.update_gso_row(kappa, size_reduction_end - 1))
      return set_status(RED_GSO_FAILURE);

    bool loop_needed = false;
    for (int j = size_reduction_end - 1; j >= size_reduction_start && !loop_needed; j--)
    {
      m.get_mu(ftmp1, kappa, j);
      ftmp1.abs(ftmp1);
      loop_needed |= (ftmp1 > eta);
    }
    if (!loop_needed)
      break;

    if (iter >= 2)
    {
      long new_max_expo = m.get_max_mu_exp(kappa, size_reduction_end);
      if (new_max_expo > max_expo - SIZE_RED_FAILURE_THRESH)
      {
        return set_status(RED_BABAI_FAILURE);
      }
      max_expo = new_max_expo;
    }

    for (int j = size_reduction_start; j < size_reduction_end; j++)
    {
      babai_mu[j] = m.get_mu_exp(kappa, j, babai_expo[j]);
    }
    m.row_op_begin(kappa, kappa + 1);
    for (int j = size_reduction_end - 1; j >= size_reduction_start; j--)
    {
      mu_m_ant.rnd_we(babai_mu[j], babai_expo[j]);
      if (mu_m_ant.zero_p())
        continue;
      // Approximate update of the mu_(kappa,k)'s
      for (int k = size_reduction_start; k < j; k++)
      {
        ftmp1.mul(mu_m_ant, m.get_mu_exp(j, k));
        /* When enable_row_expo=true, the following line relies on the fact that
           get_mu_exp(a, b, expo) returns expo = row_expo[a] - row_expo[b]. */
        babai_mu[k].sub(babai_mu[k], ftmp1);
      }
      // Operation on the basis
      // FPLLL_TRACE("Babai : row[" << kappa << "] += " << mu_m_ant << " * 2^" << babai_expo[j] << "
      // * row[" << j << "]");
      mu_m_ant.neg(mu_m_ant);
      m.row_addmul_we(kappa, j, mu_m_ant, babai_expo[j]);
    }
    m.row_op_end(kappa, kappa + 1);
  }
  return true;
}

template <class ZT, class FT>
bool is_lll_reduced(MatGSOInterface<ZT, FT> &m, double delta, double eta)
{
  FT ftmp1;
  FT ftmp2;
  FT delta_ = delta;
  m.update_gso();
  for (int i = 0; i < m.d; i++)
  {
    for (int j = 0; j < i; j++)
    {
      m.get_mu(ftmp1, i, j);
      ftmp1.abs(ftmp1);
      if (ftmp1 > eta)
        return false;
    }
  }
  for (int i = 1; i < m.d; i++)
  {
    m.get_mu(ftmp2, i, i - 1);
    ftmp2.mul(ftmp2, ftmp2);  // μ^2

    ftmp2.sub(delta_, ftmp2);  // δ - μ^2
    m.get_r(ftmp1, i - 1, i - 1);
    ftmp2.mul(ftmp1, ftmp2);  // (δ - μ^2) ⋅ r_{i-1,i-1}

    m.get_r(ftmp1, i, i);  // r_{i,i}

    if (ftmp1 < ftmp2)
      return false;
  }
  return true;
}

/** instantiate functions **/

template class LLLReduction<Z_NR<long>, FP_NR<double>>;
template class LLLReduction<Z_NR<double>, FP_NR<double>>;
template class LLLReduction<Z_NR<mpz_t>, FP_NR<double>>;
template bool
is_lll_reduced<Z_NR<mpz_t>, FP_NR<double>>(MatGSOInterface<Z_NR<mpz_t>, FP_NR<double>> &m,
                                           double delta, double eta);

#ifdef FPLLL_WITH_LONG_DOUBLE
template class LLLReduction<Z_NR<long>, FP_NR<long double>>;
template class LLLReduction<Z_NR<double>, FP_NR<long double>>;
template class LLLReduction<Z_NR<mpz_t>, FP_NR<long double>>;

template bool
is_lll_reduced<Z_NR<mpz_t>, FP_NR<long double>>(MatGSOInterface<Z_NR<mpz_t>, FP_NR<long double>> &m,
                                                double delta, double eta);
#endif

#ifdef FPLLL_WITH_QD
template class LLLReduction<Z_NR<long>, FP_NR<dd_real>>;
template class LLLReduction<Z_NR<double>, FP_NR<dd_real>>;
template class LLLReduction<Z_NR<mpz_t>, FP_NR<dd_real>>;

template bool
is_lll_reduced<Z_NR<mpz_t>, FP_NR<dd_real>>(MatGSOInterface<Z_NR<mpz_t>, FP_NR<dd_real>> &m,
                                            double delta, double eta);

template class LLLReduction<Z_NR<long>, FP_NR<qd_real>>;
template class LLLReduction<Z_NR<double>, FP_NR<qd_real>>;
template class LLLReduction<Z_NR<mpz_t>, FP_NR<qd_real>>;

template bool
is_lll_reduced<Z_NR<mpz_t>, FP_NR<qd_real>>(MatGSOInterface<Z_NR<mpz_t>, FP_NR<qd_real>> &m,
                                            double delta, double eta);
#endif

#ifdef FPLLL_WITH_DPE
template class LLLReduction<Z_NR<long>, FP_NR<dpe_t>>;
template class LLLReduction<Z_NR<double>, FP_NR<dpe_t>>;
template class LLLReduction<Z_NR<mpz_t>, FP_NR<dpe_t>>;
template bool
is_lll_reduced<Z_NR<mpz_t>, FP_NR<dpe_t>>(MatGSOInterface<Z_NR<mpz_t>, FP_NR<dpe_t>> &m,
                                          double delta, double eta);
#endif

template class LLLReduction<Z_NR<long>, FP_NR<mpfr_t>>;
template class LLLReduction<Z_NR<double>, FP_NR<mpfr_t>>;
template class LLLReduction<Z_NR<mpz_t>, FP_NR<mpfr_t>>;
template bool
is_lll_reduced<Z_NR<mpz_t>, FP_NR<mpfr_t>>(MatGSOInterface<Z_NR<mpz_t>, FP_NR<mpfr_t>> &m,
                                           double delta, double eta);

FPLLL_END_NAMESPACE
<commit_msg>instantiate all variants of is_lll_reduced<commit_after>/* Copyright (C) 2005-2008 Damien Stehle.
   Copyright (C) 2007 David Cade.
   Copyright (C) 2011 Xavier Pujol.

   This file is part of fplll. fplll 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.

   fplll 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 fplll. If not, see <http://www.gnu.org/licenses/>. */

/* Template source file */

#include "lll.h"
#include "util.h"

FPLLL_BEGIN_NAMESPACE

static inline bool is_power_of_2(int i) { return (i & (i - 1)) == 0; }

template <class ZT, class FT>
LLLReduction<ZT, FT>::LLLReduction(MatGSOInterface<ZT, FT> &m, double delta, double eta, int flags)
    : status(RED_SUCCESS), final_kappa(0), last_early_red(0), n_swaps(0), m(m)
{
  /* No early reduction in proved mode (i.e. enable_int_gram=true).
     NOTE: To make this possible, the hypothesis "g(i, j) is valid if
     0 <= i < n_known_rows and j <= i" in gso.h should be changed and
     MatGSOInterface<ZT, FT>::discover_row() should be rewritten. */
  enable_early_red = (flags & LLL_EARLY_RED) && !m.enable_int_gram;
  siegel           = flags & LLL_SIEGEL;
  verbose          = flags & LLL_VERBOSE;
  this->delta      = delta;
  this->eta        = eta;
  swap_threshold   = siegel ? delta - eta * eta : delta;
  zeros            = 0;
}

template <class ZT, class FT>
bool LLLReduction<ZT, FT>::lll(int kappa_min, int kappa_start, int kappa_end,
                               int size_reduction_start)
{
  if (kappa_end == -1)
    kappa_end = m.d;

  FPLLL_DEBUG_CHECK(kappa_min <= kappa_start && kappa_start < kappa_end && kappa_end <= m.d);
  int start_time = cputime();
  int kappa      = kappa_start + 1;
  int kappa_max  = 0;
  int d          = kappa_end - kappa_min;

  zeros       = 0;
  n_swaps     = 0;
  final_kappa = 0;
  if (verbose)
    print_params();
  extend_vect(lovasz_tests, kappa_end);
  extend_vect(babai_mu, kappa_end);
  extend_vect(babai_expo, kappa_end);

  for (; zeros < d && m.b_row_is_zero(0); zeros++)
  {
    m.move_row(kappa_min, kappa_end - 1 - zeros);
  }

  if (zeros < d && ((kappa_start > 0 && !babai(kappa_start, kappa_start, size_reduction_start)) ||
                    !m.update_gso_row(kappa_start)))
  {
    final_kappa = kappa_start;
    return false;
  }

  long long iter, max_iter;
  max_iter = static_cast<long long>(
      d - 2 * d * (d + 1) * ((m.get_max_exp_of_b() + 3) / std::log(delta.get_d())));

  for (iter = 0; iter < max_iter && kappa < kappa_end - zeros; iter++)
  {
    if (kappa > kappa_max)
    {
      if (verbose)
      {
        cerr << "Discovering vector " << kappa - kappa_min + 1 + zeros << "/" << d
             << " cputime=" << cputime() - start_time << endl;
      }
      kappa_max = kappa;
      if (enable_early_red && is_power_of_2(kappa) && kappa > last_early_red)
      {
        if (!early_reduction(kappa, size_reduction_start))
        {
          final_kappa = kappa;
          return false;
        }
      }
    }

    // Lazy size reduction
    if (!babai(kappa, kappa, size_reduction_start))
    {
      final_kappa = kappa;
      return false;
    }

    // Tests Lovasz's condition
    m.get_gram(lovasz_tests[0], kappa, kappa);
    for (int i = 1; i <= kappa; i++)
    {
      ftmp1.mul(m.get_mu_exp(kappa, i - 1), m.get_r_exp(kappa, i - 1));
      lovasz_tests[i].sub(lovasz_tests[i - 1], ftmp1);
    }
    ftmp1.mul(m.get_r_exp(kappa - 1, kappa - 1), swap_threshold);
    if (m.enable_row_expo)
    {
      ftmp1.mul_2si(ftmp1, 2 * (m.row_expo[kappa - 1] - m.row_expo[kappa]));
    }

    if (ftmp1 > lovasz_tests[siegel ? kappa : kappa - 1])
    {
      n_swaps++;
      // Failure, computes the insertion index
      int old_k = kappa;
      for (kappa--; kappa > kappa_min; kappa--)
      {
        ftmp1.mul(m.get_r_exp(kappa - 1, kappa - 1), swap_threshold);
        if (m.enable_row_expo)
        {
          ftmp1.mul_2si(ftmp1, 2 * (m.row_expo[kappa - 1] - m.row_expo[old_k]));
        }
        if (ftmp1 < lovasz_tests[siegel ? kappa : kappa - 1])
          break;
      }
      // FPLLL_TRACE("Lovasz's condition is not satisfied, kappa=" << kappa << " old_kappa=" <<
      // old_k);
      // Moves the vector
      if (lovasz_tests[kappa] > 0)
      {
        m.move_row(old_k, kappa);
      }
      else
      {
        zeros++;
        m.move_row(old_k, kappa_end - zeros);
        kappa = old_k;
        continue;
      }
    }

    m.set_r(kappa, kappa, lovasz_tests[kappa]);
    kappa++;
  }

  if (kappa < kappa_end - zeros)
    return set_status(RED_LLL_FAILURE);
  else
    return set_status(RED_SUCCESS);
}

template <class ZT, class FT>
bool LLLReduction<ZT, FT>::babai(int kappa, int size_reduction_end, int size_reduction_start)
{
  // FPLLL_TRACE_IN("kappa=" << kappa);
  long max_expo = LONG_MAX;

  for (int iter = 0;; iter++)
  {
    if (!m.update_gso_row(kappa, size_reduction_end - 1))
      return set_status(RED_GSO_FAILURE);

    bool loop_needed = false;
    for (int j = size_reduction_end - 1; j >= size_reduction_start && !loop_needed; j--)
    {
      m.get_mu(ftmp1, kappa, j);
      ftmp1.abs(ftmp1);
      loop_needed |= (ftmp1 > eta);
    }
    if (!loop_needed)
      break;

    if (iter >= 2)
    {
      long new_max_expo = m.get_max_mu_exp(kappa, size_reduction_end);
      if (new_max_expo > max_expo - SIZE_RED_FAILURE_THRESH)
      {
        return set_status(RED_BABAI_FAILURE);
      }
      max_expo = new_max_expo;
    }

    for (int j = size_reduction_start; j < size_reduction_end; j++)
    {
      babai_mu[j] = m.get_mu_exp(kappa, j, babai_expo[j]);
    }
    m.row_op_begin(kappa, kappa + 1);
    for (int j = size_reduction_end - 1; j >= size_reduction_start; j--)
    {
      mu_m_ant.rnd_we(babai_mu[j], babai_expo[j]);
      if (mu_m_ant.zero_p())
        continue;
      // Approximate update of the mu_(kappa,k)'s
      for (int k = size_reduction_start; k < j; k++)
      {
        ftmp1.mul(mu_m_ant, m.get_mu_exp(j, k));
        /* When enable_row_expo=true, the following line relies on the fact that
           get_mu_exp(a, b, expo) returns expo = row_expo[a] - row_expo[b]. */
        babai_mu[k].sub(babai_mu[k], ftmp1);
      }
      // Operation on the basis
      // FPLLL_TRACE("Babai : row[" << kappa << "] += " << mu_m_ant << " * 2^" << babai_expo[j] << "
      // * row[" << j << "]");
      mu_m_ant.neg(mu_m_ant);
      m.row_addmul_we(kappa, j, mu_m_ant, babai_expo[j]);
    }
    m.row_op_end(kappa, kappa + 1);
  }
  return true;
}

template <class ZT, class FT>
bool is_lll_reduced(MatGSOInterface<ZT, FT> &m, double delta, double eta)
{
  FT ftmp1;
  FT ftmp2;
  FT delta_ = delta;
  m.update_gso();
  for (int i = 0; i < m.d; i++)
  {
    for (int j = 0; j < i; j++)
    {
      m.get_mu(ftmp1, i, j);
      ftmp1.abs(ftmp1);
      if (ftmp1 > eta)
        return false;
    }
  }
  for (int i = 1; i < m.d; i++)
  {
    m.get_mu(ftmp2, i, i - 1);
    ftmp2.mul(ftmp2, ftmp2);  // μ^2

    ftmp2.sub(delta_, ftmp2);  // δ - μ^2
    m.get_r(ftmp1, i - 1, i - 1);
    ftmp2.mul(ftmp1, ftmp2);  // (δ - μ^2) ⋅ r_{i-1,i-1}

    m.get_r(ftmp1, i, i);  // r_{i,i}

    if (ftmp1 < ftmp2)
      return false;
  }
  return true;
}

/** instantiate functions **/

template class LLLReduction<Z_NR<long>, FP_NR<double>>;
template class LLLReduction<Z_NR<double>, FP_NR<double>>;
template class LLLReduction<Z_NR<mpz_t>, FP_NR<double>>;
template bool
is_lll_reduced<Z_NR<mpz_t>, FP_NR<double>>(MatGSOInterface<Z_NR<mpz_t>, FP_NR<double>> &m,
                                           double delta, double eta);
template bool
is_lll_reduced<Z_NR<long>, FP_NR<double>>(MatGSOInterface<Z_NR<long>, FP_NR<double>> &m,
                                           double delta, double eta);
template bool
is_lll_reduced<Z_NR<double>, FP_NR<double>>(MatGSOInterface<Z_NR<double>, FP_NR<double>> &m,
                                           double delta, double eta);

#ifdef FPLLL_WITH_LONG_DOUBLE
template class LLLReduction<Z_NR<long>, FP_NR<long double>>;
template class LLLReduction<Z_NR<double>, FP_NR<long double>>;
template class LLLReduction<Z_NR<mpz_t>, FP_NR<long double>>;

template bool
is_lll_reduced<Z_NR<mpz_t>, FP_NR<long double>>(MatGSOInterface<Z_NR<mpz_t>, FP_NR<long double>> &m,
                                                double delta, double eta);
template bool
is_lll_reduced<Z_NR<long>, FP_NR<long double>>(MatGSOInterface<Z_NR<long>, FP_NR<long double>> &m,
                                                double delta, double eta);
template bool
is_lll_reduced<Z_NR<double>, FP_NR<long double>>(MatGSOInterface<Z_NR<double>, FP_NR<long double>> &m,
                                                double delta, double eta);
#endif

#ifdef FPLLL_WITH_QD
template class LLLReduction<Z_NR<long>, FP_NR<dd_real>>;
template class LLLReduction<Z_NR<double>, FP_NR<dd_real>>;
template class LLLReduction<Z_NR<mpz_t>, FP_NR<dd_real>>;

template bool
is_lll_reduced<Z_NR<mpz_t>, FP_NR<dd_real>>(MatGSOInterface<Z_NR<mpz_t>, FP_NR<dd_real>> &m,
                                            double delta, double eta);
template bool
is_lll_reduced<Z_NR<long>, FP_NR<dd_real>>(MatGSOInterface<Z_NR<long>, FP_NR<dd_real>> &m,
                                           double delta, double eta);
template bool
is_lll_reduced<Z_NR<double>, FP_NR<dd_real>>(MatGSOInterface<Z_NR<double>, FP_NR<dd_real>> &m,
                                             double delta, double eta);

template class LLLReduction<Z_NR<long>, FP_NR<qd_real>>;
template class LLLReduction<Z_NR<double>, FP_NR<qd_real>>;
template class LLLReduction<Z_NR<mpz_t>, FP_NR<qd_real>>;

template bool
is_lll_reduced<Z_NR<mpz_t>, FP_NR<qd_real>>(MatGSOInterface<Z_NR<mpz_t>, FP_NR<qd_real>> &m,
                                            double delta, double eta);
template bool
is_lll_reduced<Z_NR<long>, FP_NR<qd_real>>(MatGSOInterface<Z_NR<long>, FP_NR<qd_real>> &m,
                                            double delta, double eta);
template bool
is_lll_reduced<Z_NR<double>, FP_NR<qd_real>>(MatGSOInterface<Z_NR<double>, FP_NR<qd_real>> &m,
                                             double delta, double eta);
#endif

#ifdef FPLLL_WITH_DPE
template class LLLReduction<Z_NR<long>, FP_NR<dpe_t>>;
template class LLLReduction<Z_NR<double>, FP_NR<dpe_t>>;
template class LLLReduction<Z_NR<mpz_t>, FP_NR<dpe_t>>;
template bool
is_lll_reduced<Z_NR<mpz_t>, FP_NR<dpe_t>>(MatGSOInterface<Z_NR<mpz_t>, FP_NR<dpe_t>> &m,
                                          double delta, double eta);
template bool
is_lll_reduced<Z_NR<long>, FP_NR<dpe_t>>(MatGSOInterface<Z_NR<long>, FP_NR<dpe_t>> &m,
                                         double delta, double eta);
template bool
is_lll_reduced<Z_NR<double>, FP_NR<dpe_t>>(MatGSOInterface<Z_NR<double>, FP_NR<dpe_t>> &m,
                                           double delta, double eta);
#endif

template class LLLReduction<Z_NR<long>, FP_NR<mpfr_t>>;
template class LLLReduction<Z_NR<double>, FP_NR<mpfr_t>>;
template class LLLReduction<Z_NR<mpz_t>, FP_NR<mpfr_t>>;
template bool
is_lll_reduced<Z_NR<mpz_t>, FP_NR<mpfr_t>>(MatGSOInterface<Z_NR<mpz_t>, FP_NR<mpfr_t>> &m,
                                           double delta, double eta);
template bool
is_lll_reduced<Z_NR<long>, FP_NR<mpfr_t>>(MatGSOInterface<Z_NR<long>, FP_NR<mpfr_t>> &m,
                                           double delta, double eta);
template bool
is_lll_reduced<Z_NR<double>, FP_NR<mpfr_t>>(MatGSOInterface<Z_NR<double>, FP_NR<mpfr_t>> &m,
                                           double delta, double eta);

FPLLL_END_NAMESPACE
<|endoftext|>


<commit_before>#ifndef GUARD_persistent_object_hpp
#define GUARD_persistent_object_hpp

#include "database_connection.hpp"
#include <jewel/decimal.hpp>
#include <boost/optional.hpp>
#include <boost/shared_ptr.hpp>
#include <stdexcept>
#include <string>

namespace sqloxx
{

/**
 * Class template for creating objects persisted to a database.
 *
 * @todo Provide for atomicity of loading and saving (not just of
 * SQL execution, but of the actual alteration of the in-memory objects).
 */
template <typename Id>
class PersistentObject
{
public:

	/**
	 * Create a PersistentObject that corresponds (or purports to correspond)
	 * to one that already exists in the database.
	 *
	 * Note that even if there is no corresponding object in the database for
	 * the given value p_id, this constructor will still proceed without
	 * complaint. The constructor does not actually perform any checks on the
	 * validity either of p_database_connection or of p_id.
	 */
	PersistentObject
	(	boost::shared_ptr<DatabaseConnection> p_database_connection,
		Id p_id
	);

	/**
	 * Create a PersistentObject that does not correspond to
	 * one that already exists in the database.
	 */
	explicit
	PersistentObject
	(	boost::shared_ptr<DatabaseConnection> p_database_connection
	);

	virtual ~PersistentObject();

	/**
	 * Calls the derived class's implementation
	 * of do_load_all, if the object is not already
	 * fully loaded. If the object does not have an id,
	 * then this function does nothing.
	 *
	 * Note the implementation is wrapped as a transaction
	 * by calls to begin_transaction and end_transaction
	 * methods of the DatabaseConnection.
	 */
	void load();

	/**
	 * Saves the state of the in-memory object to the
	 * database, overwriting the data in the database in the
	 * event of any conflict with the existing persisted data
	 * for this id. This is done by calling
	 * do_save_existing_partial (in the event the object is not
	 * fully loaded) or do_save_existing_all (in the event the object
	 * is fully loaded). The do_save_... functions should be defined in
	 * the derived class.
	 *
	 * Note the implementation is wrapped as a transaction
	 * by calls to begin_transaction and end_transaction
	 * methods of the DatabaseConnection.
	 */
	void save_existing();

	/**
	 * Saves the state of the in-memory object to the database,
	 * as an additional item, rather than overwriting existing
	 * data. This is done by calling the pure virtual function
	 * do_save_new_all, which must be defined in the derived
	 * class. Note the do_get_table_name function must also
	 * be defined in the derived class in order for this function
	 * to find an automatically generated id to assign to the object
	 * when saved. By default it is assumed that the id is an auto-
	 * incrementing integer primary key generated by SQLite. However this
	 * behaviour can be overridden by redefining the
	 * do_calculate_prospective_key function in the derived class.
	 *
	 * Note the implementation is wrapped as a transaction by call to
	 * begin_transaction and end_transaction methods of
	 * DatabaseConnection.
	 */
	void save_new();

	/**
	 * Returns the id of the object. If the object doesn't have an id,
	 * this will CRASH via an assertion failure - rather than throw.
	 */
	Id id();

protected:

	boost::shared_ptr<DatabaseConnection> database_connection();

	/**
	 * Note an object that is created anew, that does not already exist
	 * in the database, should not have an id. By having an id, an object
	 * is saying "I exist in the database".
	 */
	void set_id(Id p_id);

	Id prospective_key();

	bool has_id();

	virtual Id do_calculate_prospective_key();

	virtual void do_load_all() = 0;

	virtual void do_save_existing_all() = 0;

	virtual void do_save_existing_partial() = 0;

	virtual void do_save_new_all() = 0;

	virtual std::string do_get_table_name() = 0;

private:

	enum LoadingStatus
	{
		ghost = 0,
		loading,
		loaded
	};

	// Data members

	boost::shared_ptr<DatabaseConnection> m_database_connection;
	boost::optional<Id> m_id;
	LoadingStatus m_loading_status;
};

template <typename Id>
inline
PersistentObject<Id>::PersistentObject
(	boost::shared_ptr<DatabaseConnection> p_database_connection,
	Id p_id
):
	m_database_connection(p_database_connection),
	m_id(p_id),
	m_loading_status(ghost)
{
}

template <typename Id>
inline
PersistentObject<Id>::PersistentObject
(	boost::shared_ptr<DatabaseConnection> p_database_connection
):
	m_database_connection(p_database_connection),
	m_loading_status(ghost)
{
}

template <typename Id>
inline
PersistentObject<Id>::~PersistentObject()
{
}

template <typename Id>
inline
void
PersistentObject<Id>::load()
{
	if (m_loading_status == ghost && has_id())
	{
		m_loading_status = loading;
		m_database_connection->begin_transaction();
		do_load_all();
		m_database_connection->end_transaction();
		m_loading_status = loaded;
	}
	return;
}

template <typename Id>
inline
void
PersistentObject<Id>::save_existing()
{
	start:
	switch (m_loading_status)
	{
	case loaded:
		m_database_connection->begin_transaction();
		do_save_existing_all();
		m_database_connection->end_transaction();
		break;
	case ghost:
		m_database_connection->begin_transaction();
		do_save_existing_partial();
		m_database_connection->end_transaction();
		break;
	case loading:
		goto start;
		break;
	default:
		throw std::logic_error("Loading status not recognized.");
	}
	return;
}

template <typename Id>
inline
Id
PersistentObject<Id>::prospective_key()
{
	if (has_id())
	{
		throw std::logic_error
		(	"Object already has id so prospective_key does not apply."
		);
	}
	return do_calculate_prospective_key();
}

template <typename Id>
inline
Id
PersistentObject<Id>::do_calculate_prospective_key()
{
	return database_connection()->template next_auto_key<Id>
	(	do_get_table_name()
	);
}

template <typename Id>
inline
void
PersistentObject<Id>::save_new()
{
	m_database_connection->begin_transaction();
	Id const key = prospective_key();
	do_save_new_all();
	m_database_connection->end_transaction();
	set_id(key);
	return;
}

template <typename Id>
inline
boost::shared_ptr<DatabaseConnection>
PersistentObject<Id>::database_connection()
{
	return m_database_connection;
}

template <typename Id>
inline
Id
PersistentObject<Id>::id()
{
	return *m_id;
}

template <typename Id>
inline
void
PersistentObject<Id>::set_id(Id p_id)
{
	m_id = p_id;
	return;
}

template <typename Id>
inline
bool
PersistentObject<Id>::has_id()
{
	// Relies on the fact that m_id is a boost::optional<Id>, and
	// will convert to true if and only if it has been initialized.
	return m_id;
}

}  // namespace sqloxx

#endif  // GUARD_persistent_object

<commit_msg>Started documenting exception safety of sqloxx::PersistentObject API functions.<commit_after>#ifndef GUARD_persistent_object_hpp
#define GUARD_persistent_object_hpp

#include "database_connection.hpp"
#include <jewel/decimal.hpp>
#include <boost/optional.hpp>
#include <boost/shared_ptr.hpp>
#include <stdexcept>
#include <string>

namespace sqloxx
{

/**
 * Class template for creating objects persisted to a database.
 *
 * @todo Provide for atomicity of loading and saving (not just of
 * SQL execution, but of the actual alteration of the in-memory objects).
 *
 * @todo Unit tests.
 */
template <typename Id>
class PersistentObject
{
public:

	/**
	 * Create a PersistentObject that corresponds (or purports to correspond)
	 * to one that already exists in the database.
	 *
	 * Note that even if there is no corresponding object in the database for
	 * the given value p_id, this constructor will still proceed without
	 * complaint. The constructor does not actually perform any checks on the
	 * validity either of p_database_connection or of p_id.
	 *
	 * Exception safety: nothrow guarantee (though derived classes'
	 * constructors might, of course, throw).
	 */
	PersistentObject
	(	boost::shared_ptr<DatabaseConnection> p_database_connection,
		Id p_id
	);

	/**
	 * Create a PersistentObject that does not correspond to
	 * one that already exists in the database.
	 *
	 * Exception safety: nothrow guarantee (though derived classes'
	 * constructors might, of course, throw).
	 */
	explicit
	PersistentObject
	(	boost::shared_ptr<DatabaseConnection> p_database_connection
	);

	/**
	 * Exception safety: nothrow guarantee (though this destructor
	 * cannot, of course, offer any guarantees about the exception safety
	 * of derived classes' destructors).
	 */
	virtual ~PersistentObject();

	/**
	 * Calls the derived class's implementation
	 * of do_load_all, if the object is not already
	 * fully loaded. If the object does not have an id,
	 * then this function does nothing.
	 *
	 * Note the implementation is wrapped as a transaction
	 * by calls to begin_transaction and end_transaction
	 * methods of the DatabaseConnection.
	 */
	void load();

	/**
	 * Saves the state of the in-memory object to the
	 * database, overwriting the data in the database in the
	 * event of any conflict with the existing persisted data
	 * for this id. This is done by calling
	 * do_save_existing_partial (in the event the object is not
	 * fully loaded) or do_save_existing_all (in the event the object
	 * is fully loaded). The do_save_... functions should be defined in
	 * the derived class.
	 *
	 * Note the implementation is wrapped as a transaction
	 * by calls to begin_transaction and end_transaction
	 * methods of the DatabaseConnection.
	 */
	void save_existing();

	/**
	 * Saves the state of the in-memory object to the database,
	 * as an additional item, rather than overwriting existing
	 * data. This is done by calling the pure virtual function
	 * do_save_new_all, which must be defined in the derived
	 * class. Note the do_get_table_name function must also
	 * be defined in the derived class in order for this function
	 * to find an automatically generated id to assign to the object
	 * when saved. By default it is assumed that the id is an auto-
	 * incrementing integer primary key generated by SQLite. However this
	 * behaviour can be overridden by redefining the
	 * do_calculate_prospective_key function in the derived class.
	 *
	 * Note the implementation is wrapped as a transaction by call to
	 * begin_transaction and end_transaction methods of
	 * DatabaseConnection.
	 */
	void save_new();

	/**
	 * Returns the id of the object. If the object doesn't have an id,
	 * this will CRASH via an assertion failure - rather than throw.
	 */
	Id id();

protected:

	boost::shared_ptr<DatabaseConnection> database_connection();

	/**
	 * Note an object that is created anew, that does not already exist
	 * in the database, should not have an id. By having an id, an object
	 * is saying "I exist in the database".
	 */
	void set_id(Id p_id);

	Id prospective_key();

	/**
	 * Exception safety: nothrow guarantee.
	 */
	bool has_id();

	virtual Id do_calculate_prospective_key();

	virtual void do_load_all() = 0;

	virtual void do_save_existing_all() = 0;

	virtual void do_save_existing_partial() = 0;

	virtual void do_save_new_all() = 0;

	virtual std::string do_get_table_name() = 0;

private:

	enum LoadingStatus
	{
		ghost = 0,
		loading,
		loaded
	};

	// Data members

	boost::shared_ptr<DatabaseConnection> m_database_connection;
	boost::optional<Id> m_id;
	LoadingStatus m_loading_status;
};

template <typename Id>
inline
PersistentObject<Id>::PersistentObject
(	boost::shared_ptr<DatabaseConnection> p_database_connection,
	Id p_id
):
	m_database_connection(p_database_connection),
	m_id(p_id),
	m_loading_status(ghost)
{
}

template <typename Id>
inline
PersistentObject<Id>::PersistentObject
(	boost::shared_ptr<DatabaseConnection> p_database_connection
):
	m_database_connection(p_database_connection),
	m_loading_status(ghost)
{
}

template <typename Id>
inline
PersistentObject<Id>::~PersistentObject()
{
}

template <typename Id>
inline
void
PersistentObject<Id>::load()
{
	if (m_loading_status == ghost && has_id())
	{
		m_loading_status = loading;
		m_database_connection->begin_transaction();
		do_load_all();
		m_database_connection->end_transaction();
		m_loading_status = loaded;
	}
	return;
}

template <typename Id>
inline
void
PersistentObject<Id>::save_existing()
{
	start:
	switch (m_loading_status)
	{
	case loaded:
		m_database_connection->begin_transaction();
		do_save_existing_all();
		m_database_connection->end_transaction();
		break;
	case ghost:
		m_database_connection->begin_transaction();
		do_save_existing_partial();
		m_database_connection->end_transaction();
		break;
	case loading:
		goto start;
		break;
	default:
		throw std::logic_error("Loading status not recognized.");
	}
	return;
}

template <typename Id>
inline
Id
PersistentObject<Id>::prospective_key()
{
	if (has_id())
	{
		throw std::logic_error
		(	"Object already has id so prospective_key does not apply."
		);
	}
	return do_calculate_prospective_key();
}

template <typename Id>
inline
Id
PersistentObject<Id>::do_calculate_prospective_key()
{
	return database_connection()->template next_auto_key<Id>
	(	do_get_table_name()
	);
}

template <typename Id>
inline
void
PersistentObject<Id>::save_new()
{
	m_database_connection->begin_transaction();
	Id const key = prospective_key();
	do_save_new_all();
	m_database_connection->end_transaction();
	set_id(key);
	return;
}

template <typename Id>
inline
boost::shared_ptr<DatabaseConnection>
PersistentObject<Id>::database_connection()
{
	return m_database_connection;
}

template <typename Id>
inline
Id
PersistentObject<Id>::id()
{
	return *m_id;
}

template <typename Id>
inline
void
PersistentObject<Id>::set_id(Id p_id)
{
	m_id = p_id;
	return;
}

template <typename Id>
inline
bool
PersistentObject<Id>::has_id()
{
	// Relies on the fact that m_id is a boost::optional<Id>, and
	// will convert to true if and only if it has been initialized.
	return m_id;
}

}  // namespace sqloxx

#endif  // GUARD_persistent_object

<|endoftext|>


<commit_before>//----------------------------  dof_test.cc  ---------------------------
//    $Id$
//    Version: $Name$
//
//    Copyright (C) 1998, 1999, 2000 by the deal.II authors
//
//    This file is subject to QPL and may not be  distributed
//    without copyright and license information. Please refer
//    to the file deal.II/doc/license.html for the  text  and
//    further information on this license.
//
//----------------------------  dof_test.cc  ---------------------------

#include <dofs/dof_handler.h>
#include <grid/tria.h>
#include <grid/grid_generator.h>
#include <fe/fe_lib.lagrange.h>
#include <grid/tria_boundary.h>
#include <grid/tria_iterator.h>
#include <grid/tria_accessor.h>
#include <lac/sparse_matrix.h>
#include <dofs/dof_constraints.h>
#include <numerics/dof_renumbering.h>
#include <dofs/dof_tools.h>
#include <base/logstream.h>

#include <cmath>
#include <cstdlib>
#include <fstream>

// 1: continuous refinement of the unit square always in the middle
// 2: refinement of the circle at the boundary
// 2: refinement of a wiggled area at the boundary

ofstream logfile("dof_test.output");

template <int dim>
class Ball
  :
  public StraightBoundary<dim>
{
  public:
    virtual Point<dim>
    get_new_point_on_line (const typename Triangulation<dim>::line_iterator &line) const
      {
	Point<dim> middle = StraightBoundary<dim>::get_new_point_on_line(line);

	for (int i=0; i<dim; ++i)
	  middle(i) -= .5;
	middle *= sqrt(dim) / (sqrt(middle.square())*2);
	for (int i=0; i<dim; ++i)
	  middle(i) += .5;

	return middle;
      };

virtual Point<dim>
    get_new_point_on_quad (const typename Triangulation<dim>::quad_iterator &quad) const
      {
	Point<dim> middle = StraightBoundary<dim>::get_new_point_on_quad(quad);

	for (int i=0; i<dim; ++i)
	  middle(i) -= .5;
	middle *= sqrt(dim) / (sqrt(middle.square())*2);
	for (int i=0; i<dim; ++i)
	  middle(i) += .5;

	return middle;
      };
};

template <int dim>
class CurvedLine
  :
  public StraightBoundary<dim>
{
  public:
    virtual Point<dim>
    get_new_point_on_line (const typename Triangulation<dim>::line_iterator &line) const;

    virtual Point<dim>
    get_new_point_on_quad (const typename Triangulation<dim>::quad_iterator &quad) const;
};

template <int dim>
Point<dim>
CurvedLine<dim>::get_new_point_on_line (const typename Triangulation<dim>::line_iterator &line) const
{
  Point<dim> middle = StraightBoundary<dim>::get_new_point_on_line (line);

				   // if the line is at the top of bottom
				   // face: do a special treatment on
				   // this line. Note that if the
				   // z-value of the midpoint is either
				   // 0 or 1, then the z-values of all
				   // vertices of the line is like that
  if (dim>=3)
    if (((middle(2) == 0) || (middle(2) == 1))
				       // find out, if the line is in the
				       // interior of the top or bottom face
				       // of the domain, or at the edge.
				       // lines at the edge need to undergo
				       // the usual treatment, while for
				       // interior lines taking the midpoint
				       // is sufficient
				       //
				       // note: the trick with the boundary
				       // id was invented after the above was
				       // written, so we are not very strict
				       // here with using these flags
	&& (line->boundary_indicator() == 1))
      return middle;

double x=middle(0),
	 y=middle(1);

  if (y<x)
    if (y<1-x)
      middle(1) = 0.04*sin(6*3.141592*middle(0));
    else
      middle(0) = 1+0.04*sin(6*3.141592*middle(1));

  else
    if (y<1-x)
      middle(0) = 0.04*sin(6*3.141592*middle(1));
    else
      middle(1) = 1+0.04*sin(6*3.141592*middle(0));

  return middle;
};

template <int dim>
Point<dim>
CurvedLine<dim>::get_new_point_on_quad (const typename Triangulation<dim>::quad_iterator &quad) const
{
  Point<dim> middle = StraightBoundary<dim>::get_new_point_on_quad (quad);

				   // if the face is at the top of bottom
				   // face: do not move the midpoint in
				   // x/y direction. Note that if the
				   // z-value of the midpoint is either
				   // 0 or 1, then the z-values of all
				   // vertices of the quad is like that
  if ((middle(2) == 0) || (middle(2) == 1))
    return middle;

  double x=middle(0),
	 y=middle(1);

  if (y<x)
    if (y<1-x)
      middle(1) = 0.04*sin(6*3.141592*middle(0));
    else
      middle(0) = 1+0.04*sin(6*3.141592*middle(1));

  else
    if (y<1-x)
      middle(0) = 0.04*sin(6*3.141592*middle(1));
    else
      middle(1) = 1+0.04*sin(6*3.141592*middle(0));

  return middle;
};

template <int dim>
class TestCases
{
  public:
    TestCases ();
    virtual ~TestCases ();

    virtual void create_new ();
    virtual void run (const unsigned int testcase);

  private:
    Triangulation<dim> *tria;
    DoFHandler<dim>    *dof;
    CurvedLine<dim> curved_line;
    Ball<dim> ball;
};

template <int dim>
TestCases<dim>::TestCases () :
		tria(0), dof(0) {};

template <int dim>
TestCases<dim>::~TestCases ()
{
  if (dof)  delete dof;
  if (tria) delete tria;
};

template <int dim>
void TestCases<dim>::create_new ()
{
  if (dof  != 0) delete dof;
  if (tria != 0) delete tria;

  tria = new Triangulation<dim>();
  GridGenerator::hyper_cube(*tria);

  dof = new DoFHandler<dim> (*tria);
};

template <int dim>
void TestCases<dim>::run (const unsigned int test_case)
{
  deallog << "Dimension = " << dim
       << ", Test case = " << test_case << endl
       << endl;

  deallog << "    Making grid..." << endl;

  switch (test_case)
    {
      case 1:
      {
					 // refine first cell
	tria->begin_active()->set_refine_flag();
	tria->execute_coarsening_and_refinement ();
					 // refine first active cell
					 // on coarsest level
	tria->begin_active()->set_refine_flag ();
	tria->execute_coarsening_and_refinement ();

	Triangulation<dim>::active_cell_iterator cell;
	for (int i=0; i<(dim==2 ? 12 : 7); ++i)
	  {
					     // refine the presently
					     // second last cell 17
					     // times
	    cell = tria->last_active(tria->n_levels()-1);
	    --cell;
	    cell->set_refine_flag ();
	    tria->execute_coarsening_and_refinement ();
	  };

	break;
      }

      case 2:
      case 3:
      {
	if (dim==3)
	  {
	    tria->begin_active()->face(2)->set_boundary_indicator(1);
	    tria->begin_active()->face(4)->set_boundary_indicator(1);
	  };

					 // set the boundary function
	tria->set_boundary(1, (test_case==2)
			   ? ((Boundary<dim>&)ball) : ((Boundary<dim>&)curved_line));

					 // refine once
	tria->begin_active()->set_refine_flag();
	tria->execute_coarsening_and_refinement ();

	Triangulation<dim>::active_cell_iterator cell, endc;
	for (int i=0; i<5-dim; ++i)
	  {
	    cell = tria->begin_active();
	    endc = tria->end();

					     // refine all
					     // boundary cells
	    for (; cell!=endc; ++cell)
	      if (cell->at_boundary())
		cell->set_refine_flag();

	    tria->execute_coarsening_and_refinement();
	  };

	break;
      }
    };

deallog << "    Distributing degrees of freedom..." << endl;
  FEQ1<dim> fe;
  dof->distribute_dofs (fe);

  deallog << "    Renumbering degrees of freedom..." << endl;
  DoFRenumbering::Cuthill_McKee (*dof);

  SparsityPattern sparsity (dof->n_dofs(),
			    dof->max_couplings_between_dofs());

DoFTools::make_sparsity_pattern (*dof, sparsity);
  int unconstrained_bandwidth = sparsity.bandwidth();

  deallog << "    Writing sparsity pattern..." << endl;
  sparsity.print_gnuplot (logfile);

// computing constraints
  deallog << "    Computing constraints..." << endl;
  ConstraintMatrix constraints;
  DoFTools::make_hanging_node_constraints (*dof, constraints);
  constraints.close ();
  constraints.condense (sparsity);

  deallog << "    Writing condensed sparsity pattern..." << endl;
  sparsity.print_gnuplot (logfile);

deallog << endl
       << "    Total number of cells         = " << tria->n_cells() << endl
       << "    Total number of active cells  = " << tria->n_active_cells() << endl
       << "    Number of DoFs                = " << dof->n_dofs() << endl
       << "    Number of constraints         = " << constraints.n_constraints() << endl
       << "    Unconstrained matrix bandwidth= " << unconstrained_bandwidth << endl
       << "    Constrained matrix bandwidth  = " << sparsity.bandwidth()
       << endl << endl;

				   // release the lock that dof has to the
				   // finite element object
  dof->clear ();
};

int main ()
{
  deallog.attach(logfile);
  deallog.depth_console(0);

  for (unsigned int test_case=1; test_case<=3; ++test_case)
    {
      TestCases<2> tests;
      tests.create_new ();
      tests.run (test_case);
    };

  for (unsigned int test_case=1; test_case<=3; ++test_case)
    {
      TestCases<3> tests;
      tests.create_new ();
      tests.run (test_case);
    };

  return 0;
};

<commit_msg>Fix indentation.<commit_after>//----------------------------  dof_test.cc  ---------------------------
//    $Id$
//    Version: $Name$
//
//    Copyright (C) 1998, 1999, 2000 by the deal.II authors
//
//    This file is subject to QPL and may not be  distributed
//    without copyright and license information. Please refer
//    to the file deal.II/doc/license.html for the  text  and
//    further information on this license.
//
//----------------------------  dof_test.cc  ---------------------------

#include <dofs/dof_handler.h>
#include <grid/tria.h>
#include <grid/grid_generator.h>
#include <fe/fe_lib.lagrange.h>
#include <grid/tria_boundary.h>
#include <grid/tria_iterator.h>
#include <grid/tria_accessor.h>
#include <lac/sparse_matrix.h>
#include <dofs/dof_constraints.h>
#include <numerics/dof_renumbering.h>
#include <dofs/dof_tools.h>
#include <base/logstream.h>

#include <cmath>
#include <cstdlib>
#include <fstream>

// 1: continuous refinement of the unit square always in the middle
// 2: refinement of the circle at the boundary
// 2: refinement of a wiggled area at the boundary

ofstream logfile("dof_test.output");

template <int dim>
class Ball
  :
  public StraightBoundary<dim>
{
  public:
    virtual Point<dim>
    get_new_point_on_line (const typename Triangulation<dim>::line_iterator &line) const
      {
	Point<dim> middle = StraightBoundary<dim>::get_new_point_on_line(line);

	for (int i=0; i<dim; ++i)
	  middle(i) -= .5;
	middle *= sqrt(dim) / (sqrt(middle.square())*2);
	for (int i=0; i<dim; ++i)
	  middle(i) += .5;

	return middle;
      };

    virtual Point<dim>
    get_new_point_on_quad (const typename Triangulation<dim>::quad_iterator &quad) const
      {
	Point<dim> middle = StraightBoundary<dim>::get_new_point_on_quad(quad);

	for (int i=0; i<dim; ++i)
	  middle(i) -= .5;
	middle *= sqrt(dim) / (sqrt(middle.square())*2);
	for (int i=0; i<dim; ++i)
	  middle(i) += .5;

	return middle;
      };
};

template <int dim>
class CurvedLine
  :
  public StraightBoundary<dim>
{
  public:
    virtual Point<dim>
    get_new_point_on_line (const typename Triangulation<dim>::line_iterator &line) const;

    virtual Point<dim>
    get_new_point_on_quad (const typename Triangulation<dim>::quad_iterator &quad) const;
};

template <int dim>
Point<dim>
CurvedLine<dim>::get_new_point_on_line (const typename Triangulation<dim>::line_iterator &line) const
{
  Point<dim> middle = StraightBoundary<dim>::get_new_point_on_line (line);

				   // if the line is at the top of bottom
				   // face: do a special treatment on
				   // this line. Note that if the
				   // z-value of the midpoint is either
				   // 0 or 1, then the z-values of all
				   // vertices of the line is like that
  if (dim>=3)
    if (((middle(2) == 0) || (middle(2) == 1))
				       // find out, if the line is in the
				       // interior of the top or bottom face
				       // of the domain, or at the edge.
				       // lines at the edge need to undergo
				       // the usual treatment, while for
				       // interior lines taking the midpoint
				       // is sufficient
				       //
				       // note: the trick with the boundary
				       // id was invented after the above was
				       // written, so we are not very strict
				       // here with using these flags
	&& (line->boundary_indicator() == 1))
      return middle;

  double x=middle(0),
	 y=middle(1);

  if (y<x)
    if (y<1-x)
      middle(1) = 0.04*sin(6*3.141592*middle(0));
    else
      middle(0) = 1+0.04*sin(6*3.141592*middle(1));

  else
    if (y<1-x)
      middle(0) = 0.04*sin(6*3.141592*middle(1));
    else
      middle(1) = 1+0.04*sin(6*3.141592*middle(0));

  return middle;
};

template <int dim>
Point<dim>
CurvedLine<dim>::get_new_point_on_quad (const typename Triangulation<dim>::quad_iterator &quad) const
{
  Point<dim> middle = StraightBoundary<dim>::get_new_point_on_quad (quad);

				   // if the face is at the top of bottom
				   // face: do not move the midpoint in
				   // x/y direction. Note that if the
				   // z-value of the midpoint is either
				   // 0 or 1, then the z-values of all
				   // vertices of the quad is like that
  if ((middle(2) == 0) || (middle(2) == 1))
    return middle;

  double x=middle(0),
	 y=middle(1);

  if (y<x)
    if (y<1-x)
      middle(1) = 0.04*sin(6*3.141592*middle(0));
    else
      middle(0) = 1+0.04*sin(6*3.141592*middle(1));

  else
    if (y<1-x)
      middle(0) = 0.04*sin(6*3.141592*middle(1));
    else
      middle(1) = 1+0.04*sin(6*3.141592*middle(0));

  return middle;
};

template <int dim>
class TestCases
{
  public:
    TestCases ();
    virtual ~TestCases ();

    virtual void create_new ();
    virtual void run (const unsigned int testcase);

  private:
    Triangulation<dim> *tria;
    DoFHandler<dim>    *dof;
    CurvedLine<dim> curved_line;
    Ball<dim> ball;
};

template <int dim>
TestCases<dim>::TestCases () :
		tria(0), dof(0) {};

template <int dim>
TestCases<dim>::~TestCases ()
{
  if (dof)  delete dof;
  if (tria) delete tria;
};

template <int dim>
void TestCases<dim>::create_new ()
{
  if (dof  != 0) delete dof;
  if (tria != 0) delete tria;

  tria = new Triangulation<dim>();
  GridGenerator::hyper_cube(*tria);

  dof = new DoFHandler<dim> (*tria);
};

template <int dim>
void TestCases<dim>::run (const unsigned int test_case)
{
  deallog << "Dimension = " << dim
       << ", Test case = " << test_case << endl
       << endl;

  deallog << "    Making grid..." << endl;

  switch (test_case)
    {
      case 1:
      {
					 // refine first cell
	tria->begin_active()->set_refine_flag();
	tria->execute_coarsening_and_refinement ();
					 // refine first active cell
					 // on coarsest level
	tria->begin_active()->set_refine_flag ();
	tria->execute_coarsening_and_refinement ();

	Triangulation<dim>::active_cell_iterator cell;
	for (int i=0; i<(dim==2 ? 12 : 7); ++i)
	  {
					     // refine the presently
					     // second last cell 17
					     // times
	    cell = tria->last_active(tria->n_levels()-1);
	    --cell;
	    cell->set_refine_flag ();
	    tria->execute_coarsening_and_refinement ();
	  };

	break;
      }

      case 2:
      case 3:
      {
	if (dim==3)
	  {
	    tria->begin_active()->face(2)->set_boundary_indicator(1);
	    tria->begin_active()->face(4)->set_boundary_indicator(1);
	  };

					 // set the boundary function
	tria->set_boundary(1, (test_case==2)
			   ? ((Boundary<dim>&)ball) : ((Boundary<dim>&)curved_line));

					 // refine once
	tria->begin_active()->set_refine_flag();
	tria->execute_coarsening_and_refinement ();

	Triangulation<dim>::active_cell_iterator cell, endc;
	for (int i=0; i<5-dim; ++i)
	  {
	    cell = tria->begin_active();
	    endc = tria->end();

					     // refine all
					     // boundary cells
	    for (; cell!=endc; ++cell)
	      if (cell->at_boundary())
		cell->set_refine_flag();

	    tria->execute_coarsening_and_refinement();
	  };

	break;
      }
    };

  deallog << "    Distributing degrees of freedom..." << endl;
  FEQ1<dim> fe;
  dof->distribute_dofs (fe);

  deallog << "    Renumbering degrees of freedom..." << endl;
  DoFRenumbering::Cuthill_McKee (*dof);

  SparsityPattern sparsity (dof->n_dofs(),
			    dof->max_couplings_between_dofs());

  DoFTools::make_sparsity_pattern (*dof, sparsity);
  int unconstrained_bandwidth = sparsity.bandwidth();

  deallog << "    Writing sparsity pattern..." << endl;
  sparsity.print_gnuplot (logfile);

				   // computing constraints
  deallog << "    Computing constraints..." << endl;
  ConstraintMatrix constraints;
  DoFTools::make_hanging_node_constraints (*dof, constraints);
  constraints.close ();
  constraints.condense (sparsity);

  deallog << "    Writing condensed sparsity pattern..." << endl;
  sparsity.print_gnuplot (logfile);

  deallog << endl
	  << "    Total number of cells         = " << tria->n_cells() << endl
	  << "    Total number of active cells  = " << tria->n_active_cells() << endl
	  << "    Number of DoFs                = " << dof->n_dofs() << endl
	  << "    Number of constraints         = " << constraints.n_constraints() << endl
	  << "    Unconstrained matrix bandwidth= " << unconstrained_bandwidth << endl
	  << "    Constrained matrix bandwidth  = " << sparsity.bandwidth()
	  << endl << endl;

				   // release the lock that dof has to the
				   // finite element object
  dof->clear ();
};

int main ()
{
  deallog.attach(logfile);
  deallog.depth_console(0);

  for (unsigned int test_case=1; test_case<=3; ++test_case)
    {
      TestCases<2> tests;
      tests.create_new ();
      tests.run (test_case);
    };

  for (unsigned int test_case=1; test_case<=3; ++test_case)
    {
      TestCases<3> tests;
      tests.create_new ();
      tests.run (test_case);
    };

  return 0;
};

<|endoftext|>


<commit_before><commit_msg>Handle also FORMAT_THIRTYTWO_BIT_TC_MASK_BGRA<commit_after><|endoftext|>


<commit_before>/*
 * DIPlib 3.0 viewer
 * This file contains source for all classes need to use the DIPviewer.
 *
 * (c)2017, Wouter Caarls
 *
 * 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.
 */

#include "dipviewer.h"

#ifdef DIP__HAS_GLFW
#include "diplib/viewer/glfw.h"
using ViewerManager = dip::viewer::GLFWManager;
#else
#include "diplib/viewer/glut.h"
using ViewerManager = dip::viewer::GLUTManager;
#endif

#include "diplib/viewer/image.h"
#include "diplib/viewer/slice.h"

namespace dip { namespace viewer {

namespace {

ViewerManager* manager__ = nullptr;
size_t count__ = 0;

String getWindowTitle( String const& title ) {
   if( !title.empty()) {
      return title;
   }
   return String( "Window " ) + std::to_string( count__ );
}

inline void Create() {
   if( !manager__ ) {
      manager__ = new ViewerManager();
      count__ = 1;
   }
}

inline void Delete() {
   delete manager__;
   manager__ = nullptr;
}

} // namespace

SliceViewer::Ptr Show( Image const& image, String const& title ) {
   Create();
   SliceViewer::Ptr wdw;
   DIP_STACK_TRACE_THIS( wdw = SliceViewer::Create( image, getWindowTitle( title )));
   DIP_STACK_TRACE_THIS( manager__->createWindow( wdw ));
   ++count__;

   return wdw;
}

ImageViewer::Ptr ShowSimple( Image const& image, String const& title ) {
   DIP_THROW_IF( image.DataType() != DT_UINT8, E::DATA_TYPE_NOT_SUPPORTED );
   Create();
   Image tmp = image.QuickCopy();
   if( image.IsScalar() ) {
      tmp.ExpandSingletonTensor( 3 );
   }
   tmp.ForceNormalStrides();
   ImageViewer::Ptr wdw;
   DIP_STACK_TRACE_THIS( wdw = ImageViewer::Create( tmp, getWindowTitle( title )));
   DIP_STACK_TRACE_THIS( manager__->createWindow( wdw ));
   ++count__;

   return wdw;
}

void Spin() {
   if( !manager__ ) {
      return;
   }
   while( manager__->activeWindows()) {
      Draw();
      std::this_thread::sleep_for( std::chrono::microseconds( 100 ));
   }
   Delete();
}

void Draw() {
   if( !manager__ ) {
      return;
   }
   manager__->processEvents();
}

void CloseAll() {
   if( !manager__ ) {
      return;
   }
   manager__->destroyWindows();
   Spin();
}

}} // namespace dip::viewer
<commit_msg>Added an additional pause in `dip::viewer::Spin()` to make sure windows are intialized.<commit_after>/*
 * DIPlib 3.0 viewer
 * This file contains source for all classes need to use the DIPviewer.
 *
 * (c)2017, Wouter Caarls
 *
 * 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.
 */

#include "dipviewer.h"

#ifdef DIP__HAS_GLFW
#include "diplib/viewer/glfw.h"
using ViewerManager = dip::viewer::GLFWManager;
#else
#include "diplib/viewer/glut.h"
using ViewerManager = dip::viewer::GLUTManager;
#endif

#include "diplib/viewer/image.h"
#include "diplib/viewer/slice.h"

namespace dip { namespace viewer {

namespace {

ViewerManager* manager__ = nullptr;
size_t count__ = 0;

String getWindowTitle( String const& title ) {
   if( !title.empty()) {
      return title;
   }
   return String( "Window " ) + std::to_string( count__ );
}

inline void Create() {
   if( !manager__ ) {
      manager__ = new ViewerManager();
      count__ = 1;
   }
}

inline void Delete() {
   delete manager__;
   manager__ = nullptr;
}

} // namespace

SliceViewer::Ptr Show( Image const& image, String const& title ) {
   Create();
   SliceViewer::Ptr wdw;
   DIP_STACK_TRACE_THIS( wdw = SliceViewer::Create( image, getWindowTitle( title )));
   DIP_STACK_TRACE_THIS( manager__->createWindow( wdw ));
   ++count__;

   return wdw;
}

ImageViewer::Ptr ShowSimple( Image const& image, String const& title ) {
   DIP_THROW_IF( image.DataType() != DT_UINT8, E::DATA_TYPE_NOT_SUPPORTED );
   Create();
   Image tmp = image.QuickCopy();
   if( image.IsScalar() ) {
      tmp.ExpandSingletonTensor( 3 );
   }
   tmp.ForceNormalStrides();
   ImageViewer::Ptr wdw;
   DIP_STACK_TRACE_THIS( wdw = ImageViewer::Create( tmp, getWindowTitle( title )));
   DIP_STACK_TRACE_THIS( manager__->createWindow( wdw ));
   ++count__;

   return wdw;
}

void Spin() {
   if( !manager__ ) {
      return;
   }
   std::this_thread::sleep_for( std::chrono::seconds( 1 )); // Wait a while to make sure the windows have finished drawing
   while( manager__->activeWindows()) {
      Draw();
      std::this_thread::sleep_for( std::chrono::microseconds( 100 ));
   }
   Delete();
}

void Draw() {
   if( !manager__ ) {
      return;
   }
   manager__->processEvents();
}

void CloseAll() {
   if( !manager__ ) {
      return;
   }
   manager__->destroyWindows();
   Spin();
}

}} // namespace dip::viewer
<|endoftext|>