<commit_before>#pragma once

#include <unordered_map>
#include <memory>
#include <type_traits>
#include <tuple>

#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wc++98-compat"
#pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
#endif  // CLANG

namespace kgr {

template<typename... Types>
struct Dependency {
	using DependenciesTypes = std::tuple<Types...>;
};

using NoDependencies = Dependency<>;

struct Single {
	using ParentTypes = std::tuple<>;
};

template<typename T>
struct Service;

template<typename... Types>
struct Overrides : Single {
	using ParentTypes = std::tuple<Types...>;
};

namespace detail {

enum class enabler {};

template <bool B, typename T>
using enable_if_t = typename std::enable_if<B, T>::type;

template<int ...>
struct seq { };

template<int N, int ...S>
struct seq_gen : seq_gen<N-1, N-1, S...> { };

template<int ...S>
struct seq_gen<0, S...> {
	using type = seq<S...>;
};

struct Holder {};

template<typename T>
struct InstanceHolder final : Holder {
	explicit InstanceHolder(std::shared_ptr<T> instance) : _instance{std::move(instance)} {}

	std::shared_ptr<T> getInstance() const {
		return _instance;
	}

private:
	std::shared_ptr<T> _instance;
};

template<typename T, typename... Args>
struct CallbackHolder final : Holder {
	using callback_t = std::function<std::shared_ptr<T>(Args...)>;

	explicit CallbackHolder(callback_t callback) : _callback{std::move(callback)} {}

	std::shared_ptr<T> operator ()(Args... args) {
		return _callback(args...);
	}
private:
	callback_t _callback;
};

template<typename T, typename ...Args>
std::unique_ptr<T> make_unique( Args&& ...args )
{
    return std::unique_ptr<T>( new T( std::forward<Args>(args)... ) );
}

template <typename T> void type_id() {}
using type_id_fn = void(*)();

} // namespace detail

struct Container : std::enable_shared_from_this<Container> {
private:
	template<typename Condition, typename T = detail::enabler> using enable_if = detail::enable_if_t<Condition::value, T>;
	template<typename Condition, typename T = detail::enabler> using disable_if = detail::enable_if_t<!Condition::value, T>;
	template<typename T> using is_service_single = std::is_base_of<Single, Service<T>>;
	template<typename T> using is_abstract = std::is_abstract<T>;
	template<typename T> using is_base_of_container = std::is_base_of<Container, T>;
	template<typename T> using is_container = std::is_same<T, Container>;
	template<typename T> using dependency_types = typename Service<T>::DependenciesTypes;
	template<typename T> using parent_types = typename Service<T>::ParentTypes;
	template <typename Tuple> using tuple_seq = typename detail::seq_gen<std::tuple_size<Tuple>::value>::type;
	template<int S, typename T> using parent_element = typename std::tuple_element<S, parent_types<T>>::type;
	template<int S, typename Tuple> using tuple_element = typename std::tuple_element<S, Tuple>::type;
	using holder_ptr = std::unique_ptr<detail::Holder>;
	using holder_cont = std::unordered_map<detail::type_id_fn, holder_ptr>;
	constexpr static detail::enabler null = {};

public:
	Container() = default;
	Container(const Container &) = default;
	Container(Container &&) = default;
	Container& operator =(const Container &) = default;
	Container& operator =(Container &&) = default;
	~Container() = default;

	template<typename T>
	void instance(std::shared_ptr<T> service) {
		static_assert(is_service_single<T>::value, "instance only accept Single Service instance.");

		call_save_instance(std::move(service), tuple_seq<parent_types<T>>{});
	}

	template<typename T>
	void instance() {
		static_assert(is_service_single<T>::value, "instance only accept Single Service instance.");

		instance(make_service<T>());
	}

	template<typename T, disable_if<is_abstract<T>> = null, disable_if<is_base_of_container<T>> = null>
	std::shared_ptr<T> service() {
		return get_service<T>();
	}

	template<typename T, enable_if<is_container<T>> = null>
	std::shared_ptr<T> service() {
		return shared_from_this();
	}

	template<typename T, disable_if<is_container<T>> = null, enable_if<is_base_of_container<T>> = null>
	std::shared_ptr<T> service() {
		return std::dynamic_pointer_cast<T>(shared_from_this());
	}

	template<typename T, enable_if<is_abstract<T>> = null>
	std::shared_ptr<T> service() {
		auto it = _services.find(&detail::template type_id<T>);

		if (it != _services.end()) {
			auto holder = static_cast<detail::InstanceHolder<T>*>(it->second.get());

			if (holder) {
				return holder->getInstance();
			}
		}
		return {};
	}

	template<typename T, typename U>
	void callback(U callback) {
		static_assert(!is_service_single<T>::value, "instance does not accept Single Service.");

		save_callback<T, dependency_types<T>>(tuple_seq<dependency_types<T>>{}, callback);
	}

	virtual void init(){}

private:
	template<typename T, enable_if<is_service_single<T>> = null>
	std::shared_ptr<T> get_service() {
		auto it = _services.find(&detail::template type_id<T>);

		if (it == _services.end()) {
			auto service = make_service<T>();
			instance(service);

			return service;
		} else {
			auto holder = static_cast<detail::InstanceHolder<T>*>(it->second.get());

			if (holder) {
				return holder->getInstance();
			}
		}
		return {};
	}

	template<typename T, disable_if<is_service_single<T>> = null>
	std::shared_ptr<T> get_service() {
		return make_service<T>();
	}

	template<typename T, int ...S>
	void call_save_instance(std::shared_ptr<T> service, detail::seq<S...>) {
		save_instance<T, parent_element<S, T>...>(std::move(service));
	}

	template<typename Tuple, int ...S>
	std::tuple<std::shared_ptr<tuple_element<S, Tuple>>...> dependency(detail::seq<S...>) {
		return std::make_tuple(service<tuple_element<S, Tuple>>()...);
	}

	template<typename T, typename Tuple, int ...S>
	std::shared_ptr<T> callback_make_service(detail::seq<S...>, Tuple dependencies) const {
		auto it = _callbacks.find(&detail::template type_id<T>);

		if (it != _callbacks.end()) {
			auto holder = static_cast<detail::CallbackHolder<T, tuple_element<S, Tuple>...>*>(it->second.get());
			if (holder) {
				return (*holder)(std::get<S>(dependencies)...);
			}
		}
		return {};
	}

	template<typename T, typename Tuple, int ...S>
	std::shared_ptr<T> make_service(detail::seq<S...> seq, Tuple dependencies) const {
		auto service = callback_make_service<T, Tuple>(seq, dependencies);

		if (service) {
			return service;
		}

		return std::make_shared<T>(std::get<S>(dependencies)...);
	}

	template <typename T>
	std::shared_ptr<T> make_service() {
		auto seq = tuple_seq<dependency_types<T>>{};
		return make_service<T>(seq, dependency<dependency_types<T>>(seq));
	}

	template<typename T, typename ...Others>
	detail::enable_if_t<(sizeof...(Others) > 0), void> save_instance(std::shared_ptr<T> service) {
		save_instance<T>(service);
		save_instance<Others...>(std::move(service));
	}

	template<typename T>
	void save_instance (std::shared_ptr<T> service) {
		_services[&detail::template type_id<T>] = detail::make_unique<detail::InstanceHolder<T>>(std::move(service));
	}

	template<typename T, typename Tuple, int ...S, typename U>
	void save_callback (detail::seq<S...>, U callback) {
		_callbacks[&detail::template type_id<T>] = detail::make_unique<detail::CallbackHolder<T, std::shared_ptr<tuple_element<S, Tuple>>...>>(callback);
	}

	holder_cont _callbacks;
	holder_cont _services;
};

template<typename T = Container, typename ...Args>
std::shared_ptr<T> make_container(Args&& ...args) {
	static_assert(std::is_base_of<Container, T>::value, "make_container only accept container types.");

	auto container = std::make_shared<T>(std::forward<Args>(args)...);
	container->init();

	return container;
}

}  // namespace kgr

#if defined(__clang__)
#pragma clang diagnostic pop
#endif  // CLANG
<commit_msg>there's no need for the template disambiguator as detail is not a dependent name<commit_after>#pragma once

#include <unordered_map>
#include <memory>
#include <type_traits>
#include <tuple>

#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wc++98-compat"
#pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
#endif  // CLANG

namespace kgr {

template<typename... Types>
struct Dependency {
	using DependenciesTypes = std::tuple<Types...>;
};

using NoDependencies = Dependency<>;

struct Single {
	using ParentTypes = std::tuple<>;
};

template<typename T>
struct Service;

template<typename... Types>
struct Overrides : Single {
	using ParentTypes = std::tuple<Types...>;
};

namespace detail {

enum class enabler {};

template <bool B, typename T>
using enable_if_t = typename std::enable_if<B, T>::type;

template<int ...>
struct seq { };

template<int N, int ...S>
struct seq_gen : seq_gen<N-1, N-1, S...> { };

template<int ...S>
struct seq_gen<0, S...> {
	using type = seq<S...>;
};

struct Holder {};

template<typename T>
struct InstanceHolder final : Holder {
	explicit InstanceHolder(std::shared_ptr<T> instance) : _instance{std::move(instance)} {}

	std::shared_ptr<T> getInstance() const {
		return _instance;
	}

private:
	std::shared_ptr<T> _instance;
};

template<typename T, typename... Args>
struct CallbackHolder final : Holder {
	using callback_t = std::function<std::shared_ptr<T>(Args...)>;

	explicit CallbackHolder(callback_t callback) : _callback{std::move(callback)} {}

	std::shared_ptr<T> operator ()(Args... args) {
		return _callback(args...);
	}
private:
	callback_t _callback;
};

template<typename T, typename ...Args>
std::unique_ptr<T> make_unique( Args&& ...args )
{
    return std::unique_ptr<T>( new T( std::forward<Args>(args)... ) );
}

template <typename T> void type_id() {}
using type_id_fn = void(*)();

} // namespace detail

struct Container : std::enable_shared_from_this<Container> {
private:
	template<typename Condition, typename T = detail::enabler> using enable_if = detail::enable_if_t<Condition::value, T>;
	template<typename Condition, typename T = detail::enabler> using disable_if = detail::enable_if_t<!Condition::value, T>;
	template<typename T> using is_service_single = std::is_base_of<Single, Service<T>>;
	template<typename T> using is_abstract = std::is_abstract<T>;
	template<typename T> using is_base_of_container = std::is_base_of<Container, T>;
	template<typename T> using is_container = std::is_same<T, Container>;
	template<typename T> using dependency_types = typename Service<T>::DependenciesTypes;
	template<typename T> using parent_types = typename Service<T>::ParentTypes;
	template <typename Tuple> using tuple_seq = typename detail::seq_gen<std::tuple_size<Tuple>::value>::type;
	template<int S, typename T> using parent_element = typename std::tuple_element<S, parent_types<T>>::type;
	template<int S, typename Tuple> using tuple_element = typename std::tuple_element<S, Tuple>::type;
	using holder_ptr = std::unique_ptr<detail::Holder>;
	using holder_cont = std::unordered_map<detail::type_id_fn, holder_ptr>;
	constexpr static detail::enabler null = {};

public:
	Container() = default;
	Container(const Container &) = default;
	Container(Container &&) = default;
	Container& operator =(const Container &) = default;
	Container& operator =(Container &&) = default;
	~Container() = default;

	template<typename T>
	void instance(std::shared_ptr<T> service) {
		static_assert(is_service_single<T>::value, "instance only accept Single Service instance.");

		call_save_instance(std::move(service), tuple_seq<parent_types<T>>{});
	}

	template<typename T>
	void instance() {
		static_assert(is_service_single<T>::value, "instance only accept Single Service instance.");

		instance(make_service<T>());
	}

	template<typename T, disable_if<is_abstract<T>> = null, disable_if<is_base_of_container<T>> = null>
	std::shared_ptr<T> service() {
		return get_service<T>();
	}

	template<typename T, enable_if<is_container<T>> = null>
	std::shared_ptr<T> service() {
		return shared_from_this();
	}

	template<typename T, disable_if<is_container<T>> = null, enable_if<is_base_of_container<T>> = null>
	std::shared_ptr<T> service() {
		return std::dynamic_pointer_cast<T>(shared_from_this());
	}

	template<typename T, enable_if<is_abstract<T>> = null>
	std::shared_ptr<T> service() {
		auto it = _services.find(&detail::type_id<T>);

		if (it != _services.end()) {
			auto holder = static_cast<detail::InstanceHolder<T>*>(it->second.get());

			if (holder) {
				return holder->getInstance();
			}
		}
		return {};
	}

	template<typename T, typename U>
	void callback(U callback) {
		static_assert(!is_service_single<T>::value, "instance does not accept Single Service.");

		save_callback<T, dependency_types<T>>(tuple_seq<dependency_types<T>>{}, callback);
	}

	virtual void init(){}

private:
	template<typename T, enable_if<is_service_single<T>> = null>
	std::shared_ptr<T> get_service() {
		auto it = _services.find(&detail::type_id<T>);

		if (it == _services.end()) {
			auto service = make_service<T>();
			instance(service);

			return service;
		} else {
			auto holder = static_cast<detail::InstanceHolder<T>*>(it->second.get());

			if (holder) {
				return holder->getInstance();
			}
		}
		return {};
	}

	template<typename T, disable_if<is_service_single<T>> = null>
	std::shared_ptr<T> get_service() {
		return make_service<T>();
	}

	template<typename T, int ...S>
	void call_save_instance(std::shared_ptr<T> service, detail::seq<S...>) {
		save_instance<T, parent_element<S, T>...>(std::move(service));
	}

	template<typename Tuple, int ...S>
	std::tuple<std::shared_ptr<tuple_element<S, Tuple>>...> dependency(detail::seq<S...>) {
		return std::make_tuple(service<tuple_element<S, Tuple>>()...);
	}

	template<typename T, typename Tuple, int ...S>
	std::shared_ptr<T> callback_make_service(detail::seq<S...>, Tuple dependencies) const {
		auto it = _callbacks.find(&detail::type_id<T>);

		if (it != _callbacks.end()) {
			auto holder = static_cast<detail::CallbackHolder<T, tuple_element<S, Tuple>...>*>(it->second.get());
			if (holder) {
				return (*holder)(std::get<S>(dependencies)...);
			}
		}
		return {};
	}

	template<typename T, typename Tuple, int ...S>
	std::shared_ptr<T> make_service(detail::seq<S...> seq, Tuple dependencies) const {
		auto service = callback_make_service<T, Tuple>(seq, dependencies);

		if (service) {
			return service;
		}

		return std::make_shared<T>(std::get<S>(dependencies)...);
	}

	template <typename T>
	std::shared_ptr<T> make_service() {
		auto seq = tuple_seq<dependency_types<T>>{};
		return make_service<T>(seq, dependency<dependency_types<T>>(seq));
	}

	template<typename T, typename ...Others>
	detail::enable_if_t<(sizeof...(Others) > 0), void> save_instance(std::shared_ptr<T> service) {
		save_instance<T>(service);
		save_instance<Others...>(std::move(service));
	}

	template<typename T>
	void save_instance (std::shared_ptr<T> service) {
		_services[&detail::type_id<T>] = detail::make_unique<detail::InstanceHolder<T>>(std::move(service));
	}

	template<typename T, typename Tuple, int ...S, typename U>
	void save_callback (detail::seq<S...>, U callback) {
		_callbacks[&detail::type_id<T>] = detail::make_unique<detail::CallbackHolder<T, std::shared_ptr<tuple_element<S, Tuple>>...>>(callback);
	}

	holder_cont _callbacks;
	holder_cont _services;
};

template<typename T = Container, typename ...Args>
std::shared_ptr<T> make_container(Args&& ...args) {
	static_assert(std::is_base_of<Container, T>::value, "make_container only accept container types.");

	auto container = std::make_shared<T>(std::forward<Args>(args)...);
	container->init();

	return container;
}

}  // namespace kgr

#if defined(__clang__)
#pragma clang diagnostic pop
#endif  // CLANG
<|endoftext|>


<commit_before>/*
 * Copyright 2018 Google, Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Gabe Black
 */

#ifndef __SYSTEMC_EXT_CHANNEL_SC_SIGNAL_HH__
#define __SYSTEMC_EXT_CHANNEL_SC_SIGNAL_HH__

#include <iostream>
#include <string>
#include <vector>

#include "../core/sc_module.hh" // for sc_gen_unique_name
#include "../core/sc_prim.hh"
#include "sc_signal_inout_if.hh"
#include "warn_unimpl.hh" // for warn_unimpl

namespace sc_core
{

class sc_port_base;
class sc_trace_file;

// Nonstandard
// Despite having a warning "FOR INTERNAL USE ONLY!" in all caps above this
// class definition in the Accellera implementation, it appears in their
// examples and test programs, and so we need to have it here as well.
struct sc_trace_params
{
    sc_trace_file *tf;
    std::string name;

    sc_trace_params(sc_trace_file *tf, const std::string &name) :
        tf(tf), name(name)
    {}
};
typedef std::vector<sc_trace_params *> sc_trace_params_vec;

template <class T, sc_writer_policy WRITER_POLICY=SC_ONE_WRITER>
class sc_signal : public sc_signal_inout_if<T>,
                  public sc_prim_channel
{
  public:
    sc_signal() : sc_signal_inout_if<T>(),
                  sc_prim_channel(sc_gen_unique_name("signal"))
    {}
    explicit sc_signal(const char *name) : sc_signal_inout_if<T>(),
                                           sc_prim_channel(name)
    {}
    explicit sc_signal(const char *name, const T &initial_value) :
        sc_signal_inout_if<T>(), sc_prim_channel(name)
    {
        // Need to consume initial_value.
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
    }
    virtual ~sc_signal() {}

    virtual void
    register_port(sc_port_base &, const char *)
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
    }

    virtual const T&
    read() const
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
        return *(const T *)nullptr;
    }
    operator const T&() const
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
        return *(const T *)nullptr;
    }

    virtual sc_writer_policy
    get_writer_policy() const
    {
        return WRITER_POLICY;
    }
    virtual void
    write(const T&)
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
    }
    sc_signal<T, WRITER_POLICY> &
    operator = (const T&)
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
        return *this;
    }
    sc_signal<T, WRITER_POLICY> &
    operator = (const sc_signal<T, WRITER_POLICY> &)
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
        return *this;
    }

    virtual const sc_event &
    default_event() const
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
        return *(sc_event *)nullptr;
    }
    virtual const sc_event &
    value_changed_event() const
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
        return *(sc_event *)nullptr;
    }
    virtual bool
    event() const
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
        return false;
    }

    virtual void
    print(std::ostream & =std::cout) const
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
    }
    virtual void
    dump(std::ostream & =std::cout) const
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
    }
    virtual const char *kind() const { return "sc_signal"; }

  protected:
    virtual void
    update()
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
    }

  private:
    // Disabled
    sc_signal(const sc_signal<T, WRITER_POLICY> &) :
            sc_signal_inout_if<T>(), sc_prim_channel("")
    {}
};

template <class T, sc_writer_policy WRITER_POLICY>
inline std::ostream &
operator << (std::ostream &os, const sc_signal<T, WRITER_POLICY> &)
{
    sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
    return os;
}

template <sc_writer_policy WRITER_POLICY>
class sc_signal<bool, WRITER_POLICY> :
    public sc_signal_inout_if<bool>, public sc_prim_channel
{
  public:
    sc_signal()
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
    }
    explicit sc_signal(const char *)
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
    }
    explicit sc_signal(const char *name, const bool &initial_value) :
        sc_signal_inout_if<bool>(), sc_prim_channel(name)
    {
        // Need to consume initial_value.
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
    }
    virtual ~sc_signal()
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
    }

    virtual void
    register_port(sc_port_base &, const char *)
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
    }

    virtual const bool &
    read() const
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
        return *(const bool *)nullptr;
    }
    operator const bool &() const
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
        return *(const bool *)nullptr;
    }

    virtual sc_writer_policy
    get_writer_policy() const
    {
        return WRITER_POLICY;
    }
    virtual void
    write(const bool &)
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
    }
    sc_signal<bool, WRITER_POLICY> &
    operator = (const bool &)
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
        return *this;
    }
    sc_signal<bool, WRITER_POLICY> &
    operator = (const sc_signal<bool, WRITER_POLICY> &)
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
        return *this;
    }

    virtual const sc_event &
    default_event() const
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
        return *(sc_event *)nullptr;
    }

    virtual const sc_event &
    value_changed_event() const
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
        return *(sc_event *)nullptr;
    }
    virtual const sc_event &
    posedge_event() const
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
        return *(sc_event *)nullptr;
    }
    virtual const sc_event &
    negedge_event() const
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
        return *(sc_event *)nullptr;
    }

    virtual bool
    event() const
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
        return false;
    }
    virtual bool
    posedge() const
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
        return false;
    }
    virtual bool
    negedge() const
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
        return false;
    }

    virtual void
    print(std::ostream & =std::cout) const
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
    }
    virtual void
    dump(std::ostream & =std::cout) const
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
    }
    virtual const char *kind() const { return "sc_signal"; }

  protected:
    virtual void
    update()
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
    }

  private:
    // Disabled
    sc_signal(const sc_signal<bool, WRITER_POLICY> &) :
            sc_signal_inout_if<bool>(), sc_prim_channel("")
    {}
};

template <sc_writer_policy WRITER_POLICY>
class sc_signal<sc_dt::sc_logic, WRITER_POLICY> :
    public sc_signal_inout_if<sc_dt::sc_logic>, public sc_prim_channel
{
  public:
    sc_signal()
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
    }
    explicit sc_signal(const char *)
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
    }
    explicit sc_signal(const char *name,
            const sc_dt::sc_logic &initial_value) :
        sc_signal_inout_if<sc_dt::sc_logic>(), sc_prim_channel(name)
    {
        // Need to consume initial_value.
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
    }
    virtual ~sc_signal()
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
    }

    virtual void
    register_port(sc_port_base &, const char *)
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
    }

    virtual const sc_dt::sc_logic &
    read() const
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
        return *(const sc_dt::sc_logic *)nullptr;
    }
    operator const sc_dt::sc_logic &() const
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
        return *(const sc_dt::sc_logic *)nullptr;
    }

    virtual sc_writer_policy
    get_writer_policy() const
    {
        return WRITER_POLICY;
    }
    virtual void
    write(const sc_dt::sc_logic &)
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
    }
    sc_signal<sc_dt::sc_logic, WRITER_POLICY> &
    operator = (const sc_dt::sc_logic &)
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
        return *this;
    }
    sc_signal<sc_dt::sc_logic, WRITER_POLICY> &
    operator = (const sc_signal<sc_dt::sc_logic, WRITER_POLICY> &)
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
        return *this;
    }

    virtual const sc_event &
    default_event() const
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
        return *(sc_event *)nullptr;
    }

    virtual const sc_event &
    value_changed_event() const
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
        return *(sc_event *)nullptr;
    }
    virtual const sc_event &
    posedge_event() const
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
        return *(sc_event *)nullptr;
    }
    virtual const sc_event &
    negedge_event() const
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
        return *(sc_event *)nullptr;
    }

    virtual bool
    event() const
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
        return false;
    }
    virtual bool
    posedge() const
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
        return false;
    }
    virtual bool
    negedge() const
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
        return false;
    }

    virtual void
    print(std::ostream & =std::cout) const
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
    }
    virtual void
    dump(std::ostream & =std::cout) const
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
    }
    virtual const char *kind() const { return "sc_signal"; }

  protected:
    virtual void
    update()
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
    }

  private:
    // Disabled
    sc_signal(const sc_signal<sc_dt::sc_logic, WRITER_POLICY> &) :
            sc_signal_inout_if<sc_dt::sc_logic>(), sc_prim_channel("")
    {}
};

} // namespace sc_core

#endif  //__SYSTEMC_EXT_CHANNEL_SC_SIGNAL_HH__
<commit_msg>systemc: Add m_cur_val and m_new_val to sc_signal.<commit_after>/*
 * Copyright 2018 Google, Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Gabe Black
 */

#ifndef __SYSTEMC_EXT_CHANNEL_SC_SIGNAL_HH__
#define __SYSTEMC_EXT_CHANNEL_SC_SIGNAL_HH__

#include <iostream>
#include <string>
#include <vector>

#include "../core/sc_module.hh" // for sc_gen_unique_name
#include "../core/sc_prim.hh"
#include "sc_signal_inout_if.hh"
#include "warn_unimpl.hh" // for warn_unimpl

namespace sc_core
{

class sc_port_base;
class sc_trace_file;

// Nonstandard
// Despite having a warning "FOR INTERNAL USE ONLY!" in all caps above this
// class definition in the Accellera implementation, it appears in their
// examples and test programs, and so we need to have it here as well.
struct sc_trace_params
{
    sc_trace_file *tf;
    std::string name;

    sc_trace_params(sc_trace_file *tf, const std::string &name) :
        tf(tf), name(name)
    {}
};
typedef std::vector<sc_trace_params *> sc_trace_params_vec;

template <class T, sc_writer_policy WRITER_POLICY=SC_ONE_WRITER>
class sc_signal : public sc_signal_inout_if<T>,
                  public sc_prim_channel
{
  public:
    sc_signal() : sc_signal_inout_if<T>(),
                  sc_prim_channel(sc_gen_unique_name("signal"))
    {}
    explicit sc_signal(const char *name) : sc_signal_inout_if<T>(),
                                           sc_prim_channel(name)
    {}
    explicit sc_signal(const char *name, const T &initial_value) :
        sc_signal_inout_if<T>(), sc_prim_channel(name)
    {
        // Need to consume initial_value.
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
    }
    virtual ~sc_signal() {}

    virtual void
    register_port(sc_port_base &, const char *)
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
    }

    virtual const T&
    read() const
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
        return *(const T *)nullptr;
    }
    operator const T&() const
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
        return *(const T *)nullptr;
    }

    virtual sc_writer_policy
    get_writer_policy() const
    {
        return WRITER_POLICY;
    }
    virtual void
    write(const T&)
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
    }
    sc_signal<T, WRITER_POLICY> &
    operator = (const T&)
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
        return *this;
    }
    sc_signal<T, WRITER_POLICY> &
    operator = (const sc_signal<T, WRITER_POLICY> &)
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
        return *this;
    }

    virtual const sc_event &
    default_event() const
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
        return *(sc_event *)nullptr;
    }
    virtual const sc_event &
    value_changed_event() const
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
        return *(sc_event *)nullptr;
    }
    virtual bool
    event() const
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
        return false;
    }

    virtual void
    print(std::ostream & =std::cout) const
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
    }
    virtual void
    dump(std::ostream & =std::cout) const
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
    }
    virtual const char *kind() const { return "sc_signal"; }

  protected:
    virtual void
    update()
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
    }

    // These members which store the current and future value of the signal
    // are not specified in the standard but are referred to directly by one
    // of the tests.
    T m_cur_val;
    T m_new_val;

  private:
    // Disabled
    sc_signal(const sc_signal<T, WRITER_POLICY> &) :
            sc_signal_inout_if<T>(), sc_prim_channel("")
    {}
};

template <class T, sc_writer_policy WRITER_POLICY>
inline std::ostream &
operator << (std::ostream &os, const sc_signal<T, WRITER_POLICY> &)
{
    sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
    return os;
}

template <sc_writer_policy WRITER_POLICY>
class sc_signal<bool, WRITER_POLICY> :
    public sc_signal_inout_if<bool>, public sc_prim_channel
{
  public:
    sc_signal()
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
    }
    explicit sc_signal(const char *)
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
    }
    explicit sc_signal(const char *name, const bool &initial_value) :
        sc_signal_inout_if<bool>(), sc_prim_channel(name)
    {
        // Need to consume initial_value.
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
    }
    virtual ~sc_signal()
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
    }

    virtual void
    register_port(sc_port_base &, const char *)
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
    }

    virtual const bool &
    read() const
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
        return *(const bool *)nullptr;
    }
    operator const bool &() const
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
        return *(const bool *)nullptr;
    }

    virtual sc_writer_policy
    get_writer_policy() const
    {
        return WRITER_POLICY;
    }
    virtual void
    write(const bool &)
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
    }
    sc_signal<bool, WRITER_POLICY> &
    operator = (const bool &)
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
        return *this;
    }
    sc_signal<bool, WRITER_POLICY> &
    operator = (const sc_signal<bool, WRITER_POLICY> &)
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
        return *this;
    }

    virtual const sc_event &
    default_event() const
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
        return *(sc_event *)nullptr;
    }

    virtual const sc_event &
    value_changed_event() const
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
        return *(sc_event *)nullptr;
    }
    virtual const sc_event &
    posedge_event() const
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
        return *(sc_event *)nullptr;
    }
    virtual const sc_event &
    negedge_event() const
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
        return *(sc_event *)nullptr;
    }

    virtual bool
    event() const
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
        return false;
    }
    virtual bool
    posedge() const
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
        return false;
    }
    virtual bool
    negedge() const
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
        return false;
    }

    virtual void
    print(std::ostream & =std::cout) const
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
    }
    virtual void
    dump(std::ostream & =std::cout) const
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
    }
    virtual const char *kind() const { return "sc_signal"; }

  protected:
    virtual void
    update()
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
    }

  private:
    // Disabled
    sc_signal(const sc_signal<bool, WRITER_POLICY> &) :
            sc_signal_inout_if<bool>(), sc_prim_channel("")
    {}
};

template <sc_writer_policy WRITER_POLICY>
class sc_signal<sc_dt::sc_logic, WRITER_POLICY> :
    public sc_signal_inout_if<sc_dt::sc_logic>, public sc_prim_channel
{
  public:
    sc_signal()
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
    }
    explicit sc_signal(const char *)
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
    }
    explicit sc_signal(const char *name,
            const sc_dt::sc_logic &initial_value) :
        sc_signal_inout_if<sc_dt::sc_logic>(), sc_prim_channel(name)
    {
        // Need to consume initial_value.
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
    }
    virtual ~sc_signal()
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
    }

    virtual void
    register_port(sc_port_base &, const char *)
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
    }

    virtual const sc_dt::sc_logic &
    read() const
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
        return *(const sc_dt::sc_logic *)nullptr;
    }
    operator const sc_dt::sc_logic &() const
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
        return *(const sc_dt::sc_logic *)nullptr;
    }

    virtual sc_writer_policy
    get_writer_policy() const
    {
        return WRITER_POLICY;
    }
    virtual void
    write(const sc_dt::sc_logic &)
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
    }
    sc_signal<sc_dt::sc_logic, WRITER_POLICY> &
    operator = (const sc_dt::sc_logic &)
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
        return *this;
    }
    sc_signal<sc_dt::sc_logic, WRITER_POLICY> &
    operator = (const sc_signal<sc_dt::sc_logic, WRITER_POLICY> &)
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
        return *this;
    }

    virtual const sc_event &
    default_event() const
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
        return *(sc_event *)nullptr;
    }

    virtual const sc_event &
    value_changed_event() const
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
        return *(sc_event *)nullptr;
    }
    virtual const sc_event &
    posedge_event() const
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
        return *(sc_event *)nullptr;
    }
    virtual const sc_event &
    negedge_event() const
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
        return *(sc_event *)nullptr;
    }

    virtual bool
    event() const
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
        return false;
    }
    virtual bool
    posedge() const
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
        return false;
    }
    virtual bool
    negedge() const
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
        return false;
    }

    virtual void
    print(std::ostream & =std::cout) const
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
    }
    virtual void
    dump(std::ostream & =std::cout) const
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
    }
    virtual const char *kind() const { return "sc_signal"; }

  protected:
    virtual void
    update()
    {
        sc_channel_warn_unimpl(__PRETTY_FUNCTION__);
    }

  private:
    // Disabled
    sc_signal(const sc_signal<sc_dt::sc_logic, WRITER_POLICY> &) :
            sc_signal_inout_if<sc_dt::sc_logic>(), sc_prim_channel("")
    {}
};

} // namespace sc_core

#endif  //__SYSTEMC_EXT_CHANNEL_SC_SIGNAL_HH__
<|endoftext|>


<commit_before>#pragma once

#include <utility>

namespace gcl::functional
{
    template <class... Ts>
    struct overload : Ts... {
        using Ts::operator()...;
        using bases_types = std::tuple<Ts...>; // allow operator() function_traits
    };
    template <class... Ts>
    overload(Ts...) -> overload<Ts...>; // not required in C++20, but Msvc need this deduction guide for some reasons ...

    template <typename T>
    decltype(auto) wrap(T&& func)
    { // wrap any functor into a deductible type/value
        return [func](auto&&... args) -> decltype(auto) {
            return std::invoke(func, std::forward<decltype(args)>(args)...);
        };
    }
}

#include <gcl/mp/function_traits.hpp>

namespace gcl::functional::type_traits
{
    template <class>
    struct is_overload : std::false_type {};
    template <class... Ts>
    struct is_overload<gcl::functional::overload<Ts...>> : std::true_type {};
    template <class... Ts>
    constexpr static auto is_overload_v = is_overload<Ts...>::value;

    template <typename T>
    struct overload_arguments;
    template <typename ... Ts>
    struct overload_arguments<gcl::functional::overload<Ts...>> {
        // std::tuple<std::tuple<args1...>, std::tuple<args2...>, etc.>
        using types = std::tuple<typename gcl::mp::function_traits_t<decltype(&Ts::operator())>::arguments...>;
        // std::tuple<args1..., args2..., etc.>
        using concatenated_types =
            decltype(std::tuple_cat(typename gcl::mp::function_traits_t<decltype(&Ts::operator())>::arguments{}...));
    };
    template <typename T>
    using overload_arguments_t = typename overload_arguments<T>::type;
}

#include <functional>

namespace gcl::functional::tests::type_traits
{
    static_assert(gcl::functional::type_traits::is_overload_v<gcl::functional::overload<>>);
    static_assert(not gcl::functional::type_traits::is_overload_v<std::function<void()>>);
}<commit_msg>[functional] add more tests<commit_after>#pragma once

#include <utility>

namespace gcl::functional
{
    template <class... Ts>
    struct overload : Ts... {
        using Ts::operator()...;
        using bases_types = std::tuple<Ts...>; // allow operator() function_traits
    };
    template <class... Ts>
    overload(Ts...) -> overload<Ts...>; // not required in C++20, but Msvc need this deduction guide for some reasons ...

    template <typename T>
    decltype(auto) wrap(T&& func)
    { // wrap any functor into a deductible type/value
        return [func](auto&&... args) -> decltype(auto) {
            return std::invoke(func, std::forward<decltype(args)>(args)...);
        };
    }
}

#include <gcl/mp/function_traits.hpp>

namespace gcl::functional::type_traits
{
    template <class>
    struct is_overload : std::false_type {};
    template <class... Ts>
    struct is_overload<gcl::functional::overload<Ts...>> : std::true_type {};
    template <class... Ts>
    constexpr static auto is_overload_v = is_overload<Ts...>::value;

    template <typename T>
    struct overload_arguments;
    template <typename... Ts>
    struct overload_arguments<gcl::functional::overload<Ts...>> {
        using types = std::tuple<typename gcl::mp::function_traits_t<decltype(&Ts::operator())>::arguments...>;
        using concatenated_types =
            decltype(std::tuple_cat(typename gcl::mp::function_traits_t<decltype(&Ts::operator())>::arguments{}...));
    };
    template <typename T>
    using overload_arguments_t = typename overload_arguments<T>::types;
    template <typename T>
    using overload_concatenated_arguments_t = typename overload_arguments<T>::concatenated_types;
}

#include <functional>

namespace gcl::functional::tests::type_traits
{
    static_assert(gcl::functional::type_traits::is_overload_v<gcl::functional::overload<>>);
    static_assert(not gcl::functional::type_traits::is_overload_v<std::function<void()>>);

    using overload_type = decltype(gcl::functional::overload{[](int) {}, []() {}, [](char, double) {}});
    using overload_type_arguments_t = gcl::functional::type_traits::overload_arguments_t<overload_type>;
    static_assert(std::tuple_size_v<overload_type_arguments_t> == 3);
    static_assert(std::is_same_v<std::tuple_element_t<0, overload_type_arguments_t>, std::tuple<int>>);
    static_assert(std::is_same_v<std::tuple_element_t<1, overload_type_arguments_t>, std::tuple<>>);
    static_assert(std::is_same_v<std::tuple_element_t<2, overload_type_arguments_t>, std::tuple<char, double>>);

    using overload_type_concatenated_arguments_t =
        gcl::functional::type_traits::overload_concatenated_arguments_t<overload_type>;
    static_assert(std::tuple_size_v<overload_type_concatenated_arguments_t> == 3);
    static_assert(std::is_same_v<std::tuple_element_t<0, overload_type_concatenated_arguments_t>, int>);
    static_assert(std::is_same_v<std::tuple_element_t<1, overload_type_concatenated_arguments_t>, char>);
    static_assert(std::is_same_v<std::tuple_element_t<2, overload_type_concatenated_arguments_t>, double>);
}<|endoftext|>


<commit_before>///
/// @file  min_max.hpp
/// @brief In order to make the code more readable primecount allows
///        to use the min and max functions with different types
///        if both types are integral and type A >= type B.
///
///        int64_t a = 100;
///        int32_t b = 999;
///
///        primecount::max(a, b); // compiles
///        primecount::max(b, a); // does not compile
///
///        std::max(a, b); // does not compile
///        std::max(b, a); // does not compile
///
/// Copyright (C) 2016 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#ifndef MIN_MAX_HPP
#define MIN_MAX_HPP

#if __cplusplus >= 201103L

#include <int128_t.hpp>

#include <algorithm>
#include <type_traits>

namespace primecount {

/// Check if A and B are:
/// 1) Same types
/// 2) Different integral types which satisfy:
///      sizeof(A) > sizeof(B) ||
///     (sizeof(A) == sizeof(B) && is_unsigned<A> && is_signed<B>)
///
template <typename A, typename B>
struct is_comparable
{
  enum {
    value = std::is_same<A, B>::value || ((
            prt::is_integral<A>::value &&
            prt::is_integral<B>::value) && (
            sizeof(A) > sizeof(B) || (
            sizeof(A) == sizeof(B) &&
            std::is_unsigned<A>::value &&
            std::is_signed<B>::value)))
  };
};

/// Convenience min function for different types.
template <typename A, typename B>
inline B min(A a, B b)
{
  static_assert(is_comparable<A, B>::value,
                "min(A, B): Cannot compare types A and B");

  return (B) std::min(a, (A) b);
}

/// Convenience min function for different types.
template <typename A, typename B>
inline B min3(A a, B b, B c)
{
  static_assert(is_comparable<A, B>::value,
                "min3(A, B, B): Cannot compare types A and B");

  return (B) std::min(a, (A) std::min(b, c));
}

/// Convenience max function for different types.
template <typename A, typename B>
inline A max(A a, B b)
{
  static_assert(is_comparable<A, B>::value,
                "max(A, B): Cannot compare types A and B");

  return std::max(a, (A) b);
}

/// Convenience max function for different types.
template <typename A, typename B>
inline A max3(A a, B b, B c)
{
  static_assert(is_comparable<A, B>::value,
                "max3(A, B, B): Cannot compare types A and B");

  return std::max(a, (A) std::max(b, c));
}

} // namespace

#else /* C++98 */

#include <algorithm>
#include <cassert>

namespace primecount {

template <typename A, typename B>
inline B min(A a, B b)
{
  assert(sizeof(A) >= sizeof(B));
  return (B) std::min(a, (A) b);
}

template <typename A, typename B>
inline B min3(A a, B b, B c)
{
  assert(sizeof(A) >= sizeof(B));
  return (B) std::min(a, (A) std::min(b, c));
}

template <typename A, typename B>
inline A max(A a, B b)
{
  assert(sizeof(A) >= sizeof(B));
  return std::max(a, (A) b);
}

template <typename A, typename B>
inline A max3(A a, B b, B c)
{
  assert(sizeof(A) >= sizeof(B));
  return std::max(a, (A) std::max(b, c));
}

} // namespace

#endif

#endif // MIN_MAX_HPP
<commit_msg>Make C++11 only<commit_after>///
/// @file  min_max.hpp
/// @brief Template min and max functions that allow comparing
///        different types if both types are integral
///        and sizeof(A) >= sizeof(B).
///
/// Copyright (C) 2017 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#ifndef MIN_MAX_HPP
#define MIN_MAX_HPP

#include <int128_t.hpp>

#include <algorithm>
#include <type_traits>

namespace primecount {

/// Check if A and B are:
/// 1) Same types
/// 2) Different integral types which satisfy:
///      sizeof(A) > sizeof(B) ||
///     (sizeof(A) == sizeof(B) && is_unsigned<A> && is_signed<B>)
///
template <typename A, typename B>
struct is_comparable
{
  enum {
    value = std::is_same<A, B>::value || ((
            prt::is_integral<A>::value &&
            prt::is_integral<B>::value) && (
            sizeof(A) > sizeof(B) || (
            sizeof(A) == sizeof(B) &&
            std::is_unsigned<A>::value &&
            std::is_signed<B>::value)))
  };
};

template <typename A, typename B>
inline B min(A a, B b)
{
  static_assert(is_comparable<A, B>::value,
                "min(A, B): Cannot compare types A and B");

  return (B) std::min(a, (A) b);
}

template <typename A, typename B>
inline B min3(A a, B b, B c)
{
  static_assert(is_comparable<A, B>::value,
                "min3(A, B, B): Cannot compare types A and B");

  return (B) std::min(a, (A) std::min(b, c));
}

template <typename A, typename B>
inline A max(A a, B b)
{
  static_assert(is_comparable<A, B>::value,
                "max(A, B): Cannot compare types A and B");

  return std::max(a, (A) b);
}

template <typename A, typename B>
inline A max3(A a, B b, B c)
{
  static_assert(is_comparable<A, B>::value,
                "max3(A, B, B): Cannot compare types A and B");

  return std::max(a, (A) std::max(b, c));
}

} // namespace

#endif
<|endoftext|>


<commit_before>/*
  The MIT License (MIT)
  Copyright (c) 2016 Xu Cheng
  See licensing at:
    https://opensource.org/licenses/MIT
*/

#pragma once

#include <exception>
#include <string>
#include "pbc-streamopen.hpp"

namespace pbc
{
    namespace backend
    {
#include <pbc/pbc.h>
    };

    class NotInitializedError : public std::runtime_error
    {
    public:
        NotInitializedError() : runtime_error("Object is not initialized.") {}
    };

    class AlreadyInitializedError : public std::runtime_error
    {
    public:
        AlreadyInitializedError()
            : runtime_error("Object is already initialized.")
        {
        }
    };

    class InitializationError : public std::runtime_error
    {
    public:
        InitializationError() : runtime_error("Failed to initialize object.") {}
        InitializationError(const std::string& msg) : runtime_error(msg) {}
    };

    class ElementTypeError : public std::runtime_error
    {
    public:
        ElementTypeError() : runtime_error("Element has wrong type.") {}
    }

    class Pairing;
    class PairingParam;
    class Element;
    typedef std::shared_ptr<Pairing> PairingPtr;
    typedef std::shared_ptr<PairingParam> PairingParamPtr;
    typedef std::shared_ptr<Element> ElementPtr;

    class PairingParam
    {
    public:
        PairingParam() = default;
        PairingParam(const PairingParam&) = delete;
        ~PairingParam() { backend::pbc_param_clear(_param); }
        std::string to_str() const
        {
            std::stringstream buf;
            backend::stream_fd_ptr sfd = backend::streamopen(buf);
            backend::pbc_param_out_str(sfd->fd,
                                       *(backend::pbc_param_t*)&_param);
            backend::streamclose(sfd);
            return buf.str();
        }

        static PairingParamPtr init_from_str(const std::string& param_str)
        {
            PairingParamPtr ptr = std::make_shared<PairingParam>();
            if (backend::pbc_param_init_set_str(ptr->_param,
                                                param_str.c_str()) != 0)
                throw InitializationError(
                    "Failed to initialize pairing parameter.");
            return ptr;
        }
        static PairingParamPtr gen_type_a(int rbits = 160, int qbits = 512)
        {
            PairingParamPtr ptr = std::make_shared<PairingParam>();
            backend::pbc_param_init_a_gen(ptr->_param, rbits, qbits);
            return ptr;
        }
        static PairingParamPtr gen_type_i(int group_size = 696)
        {
            PairingParamPtr ptr = std::make_shared<PairingParam>();
            backend::pbc_param_init_i_gen(ptr->_param, group_size);
            return ptr;
        }
        static PairingParamPtr gen_type_e(int rbits = 160, int qbits = 1024)
        {
            PairingParamPtr ptr = std::make_shared<PairingParam>();
            backend::pbc_param_init_e_gen(ptr->_param, rbits, qbits);
            return ptr;
        }
        static PairingParamPtr gen_type_f(int bits = 160)
        {
            PairingParamPtr ptr = std::make_shared<PairingParam>();
            backend::pbc_param_init_f_gen(ptr->_param, bits);
            return ptr;
        }

    private:
        friend class Pairing;
        backend::pbc_param_t _param;
    };

    class Pairing
    {
    public:
        Pairing() = default;
        Pairing(const Pairing&) = delete;
        ~Pairing() { pairing_clear(_pairing); }
        static PairingPtr init_from_param_str(const std::string& param_str)
        {
            return Pairing::init_from_param(
                PairingParam::init_from_str(param_str));
            PairingPtr ptr = std::make_shared<Pairing>();
            if (backend::pairing_init_set_str(ptr->_pairing,
                                              param_str.c_str()) != 0)
                throw InitializationError("Failed to initialize pairing.");
            return ptr;
        }
        static PairingPtr init_from_param(const PairingParamPtr& param)
        {
            PairingPtr ptr = std::make_shared<Pairing>();
            backend::pairing_init_pbc_param(ptr->_pairing, param->_param);
            return ptr;
        }

        bool symmetric() const
        {
            return backend::pairing_is_symmetric(
                *(backend::pairing_t*)&_pairing);
        }
        int g1_bytes_length() const
        {
            return backend::pairing_length_in_bytes_G1(
                *(backend::pairing_t*)&_pairing);
        }
        int g1_x_only_bytes_length() const
        {
            return backend::pairing_length_in_bytes_x_only_G1(
                *(backend::pairing_t*)&_pairing);
        }
        int g1_compressed_bytes_length() const
        {
            return backend::pairing_length_in_bytes_compressed_G1(
                *(backend::pairing_t*)&_pairing);
        }
        int g2_bytes_length() const
        {
            return backend::pairing_length_in_bytes_G2(
                *(backend::pairing_t*)&_pairing);
        }
        int g2_x_only_bytes_length() const
        {
            return backend::pairing_length_in_bytes_x_only_G2(
                *(backend::pairing_t*)&_pairing);
        }
        int g2_compressed_bytes_length() const
        {
            return backend::pairing_length_in_bytes_compressed_G2(
                *(backend::pairing_t*)&_pairing);
        }
        int gt_bytes_length() const
        {
            return backend::pairing_length_in_bytes_GT(
                *(backend::pairing_t*)&_pairing);
        }
        int zr_bytes_length() const
        {
            return backend::pairing_length_in_bytes_Zr(
                *(backend::pairing_t*)&_pairing);
        }

    private:
        friend class Element;
        backend::pairing_t _pairing;
    };

    enum class ElementType { G1, G2, GT, Zr, NotInitialized };

    std::ostream& operator<<(std::ostream& o, ElementType type)
    {
        switch (type) {
            case ElementType::G1: o << "G1"; break;
            case ElementType::G2: o << "G2"; break;
            case ElementType::GT: o << "GT"; break;
            case ElementType::Zr: o << "Zr"; break;
            case ElementType::NotInitialized: o << "NotInitialized"; break;
        }
        return o;
    }

    class Element
    {
    public:
        Element() : _type(ElementType::NotInitialized) {}
        Element(const Element& e) : _type(e._type)
        {
            if (_type != ElementType::NotInitialized) {
                backend::element_init_same_as(
                    _element, *(backend::element_t*)&e._element);
                backend::element_set(_element,
                                     *(backend::element_t*)&e._element);
            }
        }
        Element(Element&& e) noexcept : _type(e._type)
        {
            std::memcpy(&_element[0], &e._element[0],
                        sizeof(backend::element_t));
            e._type = ElementType::NotInitialized;
        }
        ~Element()
        {
            if (_type != ElementType::NotInitialized) {
                backend::element_clear(_element);
                _type = ElementType::NotInitialized;
            }
        }

#define Element_Init_Func(type, type_lowercase)                    \
    void init_##type_lowercase(const PairingPtr pairing)           \
    {                                                              \
        if (_type != ElementType::NotInitialized)                  \
            throw AlreadyInitializedError();                       \
        backend::element_init_##type(_element, pairing->_pairing); \
        _type = ElementType::type;                                 \
    }

        Element_Init_Func(G1, g1);
        Element_Init_Func(G2, g2);
        Element_Init_Func(GT, gt);
        Element_Init_Func(Zr, zr);
#undef Element_Init_Func

        void init_same_as(const Element& e)
        {
            if (_type != ElementType::NotInitialized)
                throw AlreadyInitializedError();
            if (e._type == ElementType::NotInitialized)
                throw NotInitializedError();
            backend::element_init_same_as(_element,
                                          *(backend::element_t*)&e._element);
            _type = e._type;
        }

        ElementType type() const { return _type; }
        std::string to_str(int base = 10) const
        {
            if (_type == ElementType::NotInitialized)
                throw NotInitializedError();
            std::stringstream buf;
            backend::stream_fd_ptr sfd = backend::streamopen(buf);
            backend::element_out_str(sfd->fd, base,
                                     *(backend::element_t*)&_element);
            backend::streamclose(sfd);
            return buf.str();
        }

        Element& operator=(Element&& e)
        {
            std::memcpy(&_element[0], &e._element[0],
                        sizeof(backend::element_t));
            _type = e._type;
            e._type = ElementType::NotInitialized;
            return *this;
        }
        Element& operator=(const Element& e)
        {
            if (_type != ElementType::NotInitialized && _type != e._type) {
                backend::element_clear(_element);
                if (e._type != ElementType::NotInitialized)
                    backend::element_init_same_as(
                        _element, *(backend::element_t*)&e._element);
            }
            if (e._type != ElementType::NotInitialized)
                backend::element_set(_element,
                                     *(backend::element_t*)&e._element);
            _type = e._type;
            return *this;
        }
        Element& operator=(int i)
        {
            if (_type == ElementType::NotInitialized)
                throw NotInitializedError();
            backend::element_set_si(_element, i);
            return *this;
        }
        Element& random()
        {
            if (_type == ElementType::NotInitialized)
                throw NotInitializedError();
            backend::element_random(_element);
            return *this;
        }
        Element& from_str(const std::string& s, int base = 10)
        {
            if (_type == ElementType::NotInitialized)
                throw NotInitializedError();
            backend::element_set_str(_element, s.c_str(), base);
            return *this;
        }

        bool operator==(const Element& e) const
        {
            if (_type == ElementType::NotInitialized ||
                e._type == ElementType::NotInitialized)
                return false;
            else if (_type != e._type)
                return false;
            else
                return backend::element_cmp(
                           *(backend::element_t*)&_element,
                           *(backend::element_t*)&e._element) == 0;
        }
        bool operator==(int i) const
        {
            if (_type == ElementType::NotInitialized) return false;
            Element e;
            e.init_same_as(*this);
            e = i;
            return operator==(e);
        }
        bool operator!=(const Element& e) const { return !operator==(e); }
        bool operator!=(int i) const { return !operator==(i); }
        Element operator+(const Element& e) const
        {
            if (_type == ElementType::NotInitialized ||
                e._type == ElementType::NotInitialized)
                throw NotInitializedError();
            if (_type != e._type) throw ElementTypeError();
            Element out;
            out.init_same_as(*this);
            backend::element_add(out._element, *(backend::element_t*)&_element,
                                 *(backend::element_t*)&e._element);
            return out;
        }
        Element operator+=(const Element& e)
        {
            operator=(operator+(e));
            return *this;
        }

        Element operator-(const Element& e) const
        {
            if (_type == ElementType::NotInitialized ||
                e._type == ElementType::NotInitialized)
                throw NotInitializedError();
            if (_type != e._type) throw ElementTypeError();
            Element out;
            out.init_same_as(*this);
            backend::element_sub(out._element, *(backend::element_t*)&_element,
                                 *(backend::element_t*)&e._element);
            return out;
        }
        Element operator-=(const Element& e)
        {
            operator=(operator-(e));
            return *this;
        }

        Element operator*(int i) const
        {
            if (_type == ElementType::NotInitialized)
                throw NotInitializedError();
            Element out;
            out.init_same_as(*this);
            backend::element_mul_si(out._element,
                                    *(backend::element_t*)&_element, i);
            return out;
        }
        Element operator*(const Element& e) const
        {
            if (_type == ElementType::NotInitialized ||
                e._type == ElementType::NotInitialized)
                throw NotInitializedError();
            if (e._type != ElementType::Zr) throw ElementTypeError();
            Element out;
            out.init_same_as(*this);
            backend::element_mul_zn(out._element,
                                    *(backend::element_t*)&_element,
                                    *(backend::element_t*)&e._element);
            return out;
        }
        Element operator*=(int i)
        {
            operator=(operator*(i));
            return *this;
        }
        Element operator*=(const Element& e)
        {
            operator=(operator*(e));
            return *this;
        }

        Element operator/(const Element& e) const
        {
            if (_type == ElementType::NotInitialized ||
                e._type == ElementType::NotInitialized)
                throw NotInitializedError();
            if (_type != e._type) throw ElementTypeError();
            Element out;
            out.init_same_as(*this);
            backend::element_div(out._element, *(backend::element_t*)&_element,
                                 *(backend::element_t*)&e._element);
            return out;
        }
        Element operator/=(const Element& e)
        {
            operator=(operator/(e));
            return *this;
        }

        Element operator-() const
        {
            if (_type == ElementType::NotInitialized)
                throw NotInitializedError();
            Element out;
            out.init_same_as(*this);
            backend::element_neg(out._element, *(backend::element_t*)&_element);
            return out;
        }

    private:
        backend::element_t _element;
        ElementType _type;
    };

    std::ostream& operator<<(std::ostream& o, const Element& e)
    {
        o << e.to_str();
        return o;
    }
};
<commit_msg>add missing ;<commit_after>/*
  The MIT License (MIT)
  Copyright (c) 2016 Xu Cheng
  See licensing at:
    https://opensource.org/licenses/MIT
*/

#pragma once

#include <exception>
#include <string>
#include "pbc-streamopen.hpp"

namespace pbc
{
    namespace backend
    {
#include <pbc/pbc.h>
    };

    class NotInitializedError : public std::runtime_error
    {
    public:
        NotInitializedError() : runtime_error("Object is not initialized.") {}
    };

    class AlreadyInitializedError : public std::runtime_error
    {
    public:
        AlreadyInitializedError()
            : runtime_error("Object is already initialized.")
        {
        }
    };

    class InitializationError : public std::runtime_error
    {
    public:
        InitializationError() : runtime_error("Failed to initialize object.") {}
        InitializationError(const std::string& msg) : runtime_error(msg) {}
    };

    class ElementTypeError : public std::runtime_error
    {
    public:
        ElementTypeError() : runtime_error("Element has wrong type.") {}
    };

    class Pairing;
    class PairingParam;
    class Element;
    typedef std::shared_ptr<Pairing> PairingPtr;
    typedef std::shared_ptr<PairingParam> PairingParamPtr;
    typedef std::shared_ptr<Element> ElementPtr;

    class PairingParam
    {
    public:
        PairingParam() = default;
        PairingParam(const PairingParam&) = delete;
        ~PairingParam() { backend::pbc_param_clear(_param); }
        std::string to_str() const
        {
            std::stringstream buf;
            backend::stream_fd_ptr sfd = backend::streamopen(buf);
            backend::pbc_param_out_str(sfd->fd,
                                       *(backend::pbc_param_t*)&_param);
            backend::streamclose(sfd);
            return buf.str();
        }

        static PairingParamPtr init_from_str(const std::string& param_str)
        {
            PairingParamPtr ptr = std::make_shared<PairingParam>();
            if (backend::pbc_param_init_set_str(ptr->_param,
                                                param_str.c_str()) != 0)
                throw InitializationError(
                    "Failed to initialize pairing parameter.");
            return ptr;
        }
        static PairingParamPtr gen_type_a(int rbits = 160, int qbits = 512)
        {
            PairingParamPtr ptr = std::make_shared<PairingParam>();
            backend::pbc_param_init_a_gen(ptr->_param, rbits, qbits);
            return ptr;
        }
        static PairingParamPtr gen_type_i(int group_size = 696)
        {
            PairingParamPtr ptr = std::make_shared<PairingParam>();
            backend::pbc_param_init_i_gen(ptr->_param, group_size);
            return ptr;
        }
        static PairingParamPtr gen_type_e(int rbits = 160, int qbits = 1024)
        {
            PairingParamPtr ptr = std::make_shared<PairingParam>();
            backend::pbc_param_init_e_gen(ptr->_param, rbits, qbits);
            return ptr;
        }
        static PairingParamPtr gen_type_f(int bits = 160)
        {
            PairingParamPtr ptr = std::make_shared<PairingParam>();
            backend::pbc_param_init_f_gen(ptr->_param, bits);
            return ptr;
        }

    private:
        friend class Pairing;
        backend::pbc_param_t _param;
    };

    class Pairing
    {
    public:
        Pairing() = default;
        Pairing(const Pairing&) = delete;
        ~Pairing() { pairing_clear(_pairing); }
        static PairingPtr init_from_param_str(const std::string& param_str)
        {
            return Pairing::init_from_param(
                PairingParam::init_from_str(param_str));
            PairingPtr ptr = std::make_shared<Pairing>();
            if (backend::pairing_init_set_str(ptr->_pairing,
                                              param_str.c_str()) != 0)
                throw InitializationError("Failed to initialize pairing.");
            return ptr;
        }
        static PairingPtr init_from_param(const PairingParamPtr& param)
        {
            PairingPtr ptr = std::make_shared<Pairing>();
            backend::pairing_init_pbc_param(ptr->_pairing, param->_param);
            return ptr;
        }

        bool symmetric() const
        {
            return backend::pairing_is_symmetric(
                *(backend::pairing_t*)&_pairing);
        }
        int g1_bytes_length() const
        {
            return backend::pairing_length_in_bytes_G1(
                *(backend::pairing_t*)&_pairing);
        }
        int g1_x_only_bytes_length() const
        {
            return backend::pairing_length_in_bytes_x_only_G1(
                *(backend::pairing_t*)&_pairing);
        }
        int g1_compressed_bytes_length() const
        {
            return backend::pairing_length_in_bytes_compressed_G1(
                *(backend::pairing_t*)&_pairing);
        }
        int g2_bytes_length() const
        {
            return backend::pairing_length_in_bytes_G2(
                *(backend::pairing_t*)&_pairing);
        }
        int g2_x_only_bytes_length() const
        {
            return backend::pairing_length_in_bytes_x_only_G2(
                *(backend::pairing_t*)&_pairing);
        }
        int g2_compressed_bytes_length() const
        {
            return backend::pairing_length_in_bytes_compressed_G2(
                *(backend::pairing_t*)&_pairing);
        }
        int gt_bytes_length() const
        {
            return backend::pairing_length_in_bytes_GT(
                *(backend::pairing_t*)&_pairing);
        }
        int zr_bytes_length() const
        {
            return backend::pairing_length_in_bytes_Zr(
                *(backend::pairing_t*)&_pairing);
        }

    private:
        friend class Element;
        backend::pairing_t _pairing;
    };

    enum class ElementType { G1, G2, GT, Zr, NotInitialized };

    std::ostream& operator<<(std::ostream& o, ElementType type)
    {
        switch (type) {
            case ElementType::G1: o << "G1"; break;
            case ElementType::G2: o << "G2"; break;
            case ElementType::GT: o << "GT"; break;
            case ElementType::Zr: o << "Zr"; break;
            case ElementType::NotInitialized: o << "NotInitialized"; break;
        }
        return o;
    }

    class Element
    {
    public:
        Element() : _type(ElementType::NotInitialized) {}
        Element(const Element& e) : _type(e._type)
        {
            if (_type != ElementType::NotInitialized) {
                backend::element_init_same_as(
                    _element, *(backend::element_t*)&e._element);
                backend::element_set(_element,
                                     *(backend::element_t*)&e._element);
            }
        }
        Element(Element&& e) noexcept : _type(e._type)
        {
            std::memcpy(&_element[0], &e._element[0],
                        sizeof(backend::element_t));
            e._type = ElementType::NotInitialized;
        }
        ~Element()
        {
            if (_type != ElementType::NotInitialized) {
                backend::element_clear(_element);
                _type = ElementType::NotInitialized;
            }
        }

#define Element_Init_Func(type, type_lowercase)                    \
    void init_##type_lowercase(const PairingPtr pairing)           \
    {                                                              \
        if (_type != ElementType::NotInitialized)                  \
            throw AlreadyInitializedError();                       \
        backend::element_init_##type(_element, pairing->_pairing); \
        _type = ElementType::type;                                 \
    }

        Element_Init_Func(G1, g1);
        Element_Init_Func(G2, g2);
        Element_Init_Func(GT, gt);
        Element_Init_Func(Zr, zr);
#undef Element_Init_Func

        void init_same_as(const Element& e)
        {
            if (_type != ElementType::NotInitialized)
                throw AlreadyInitializedError();
            if (e._type == ElementType::NotInitialized)
                throw NotInitializedError();
            backend::element_init_same_as(_element,
                                          *(backend::element_t*)&e._element);
            _type = e._type;
        }

        ElementType type() const { return _type; }
        std::string to_str(int base = 10) const
        {
            if (_type == ElementType::NotInitialized)
                throw NotInitializedError();
            std::stringstream buf;
            backend::stream_fd_ptr sfd = backend::streamopen(buf);
            backend::element_out_str(sfd->fd, base,
                                     *(backend::element_t*)&_element);
            backend::streamclose(sfd);
            return buf.str();
        }

        Element& operator=(Element&& e)
        {
            std::memcpy(&_element[0], &e._element[0],
                        sizeof(backend::element_t));
            _type = e._type;
            e._type = ElementType::NotInitialized;
            return *this;
        }
        Element& operator=(const Element& e)
        {
            if (_type != ElementType::NotInitialized && _type != e._type) {
                backend::element_clear(_element);
                if (e._type != ElementType::NotInitialized)
                    backend::element_init_same_as(
                        _element, *(backend::element_t*)&e._element);
            }
            if (e._type != ElementType::NotInitialized)
                backend::element_set(_element,
                                     *(backend::element_t*)&e._element);
            _type = e._type;
            return *this;
        }
        Element& operator=(int i)
        {
            if (_type == ElementType::NotInitialized)
                throw NotInitializedError();
            backend::element_set_si(_element, i);
            return *this;
        }
        Element& random()
        {
            if (_type == ElementType::NotInitialized)
                throw NotInitializedError();
            backend::element_random(_element);
            return *this;
        }
        Element& from_str(const std::string& s, int base = 10)
        {
            if (_type == ElementType::NotInitialized)
                throw NotInitializedError();
            backend::element_set_str(_element, s.c_str(), base);
            return *this;
        }

        bool operator==(const Element& e) const
        {
            if (_type == ElementType::NotInitialized ||
                e._type == ElementType::NotInitialized)
                return false;
            else if (_type != e._type)
                return false;
            else
                return backend::element_cmp(
                           *(backend::element_t*)&_element,
                           *(backend::element_t*)&e._element) == 0;
        }
        bool operator==(int i) const
        {
            if (_type == ElementType::NotInitialized) return false;
            Element e;
            e.init_same_as(*this);
            e = i;
            return operator==(e);
        }
        bool operator!=(const Element& e) const { return !operator==(e); }
        bool operator!=(int i) const { return !operator==(i); }
        Element operator+(const Element& e) const
        {
            if (_type == ElementType::NotInitialized ||
                e._type == ElementType::NotInitialized)
                throw NotInitializedError();
            if (_type != e._type) throw ElementTypeError();
            Element out;
            out.init_same_as(*this);
            backend::element_add(out._element, *(backend::element_t*)&_element,
                                 *(backend::element_t*)&e._element);
            return out;
        }
        Element operator+=(const Element& e)
        {
            operator=(operator+(e));
            return *this;
        }

        Element operator-(const Element& e) const
        {
            if (_type == ElementType::NotInitialized ||
                e._type == ElementType::NotInitialized)
                throw NotInitializedError();
            if (_type != e._type) throw ElementTypeError();
            Element out;
            out.init_same_as(*this);
            backend::element_sub(out._element, *(backend::element_t*)&_element,
                                 *(backend::element_t*)&e._element);
            return out;
        }
        Element operator-=(const Element& e)
        {
            operator=(operator-(e));
            return *this;
        }

        Element operator*(int i) const
        {
            if (_type == ElementType::NotInitialized)
                throw NotInitializedError();
            Element out;
            out.init_same_as(*this);
            backend::element_mul_si(out._element,
                                    *(backend::element_t*)&_element, i);
            return out;
        }
        Element operator*(const Element& e) const
        {
            if (_type == ElementType::NotInitialized ||
                e._type == ElementType::NotInitialized)
                throw NotInitializedError();
            if (e._type != ElementType::Zr) throw ElementTypeError();
            Element out;
            out.init_same_as(*this);
            backend::element_mul_zn(out._element,
                                    *(backend::element_t*)&_element,
                                    *(backend::element_t*)&e._element);
            return out;
        }
        Element operator*=(int i)
        {
            operator=(operator*(i));
            return *this;
        }
        Element operator*=(const Element& e)
        {
            operator=(operator*(e));
            return *this;
        }

        Element operator/(const Element& e) const
        {
            if (_type == ElementType::NotInitialized ||
                e._type == ElementType::NotInitialized)
                throw NotInitializedError();
            if (_type != e._type) throw ElementTypeError();
            Element out;
            out.init_same_as(*this);
            backend::element_div(out._element, *(backend::element_t*)&_element,
                                 *(backend::element_t*)&e._element);
            return out;
        }
        Element operator/=(const Element& e)
        {
            operator=(operator/(e));
            return *this;
        }

        Element operator-() const
        {
            if (_type == ElementType::NotInitialized)
                throw NotInitializedError();
            Element out;
            out.init_same_as(*this);
            backend::element_neg(out._element, *(backend::element_t*)&_element);
            return out;
        }

    private:
        backend::element_t _element;
        ElementType _type;
    };

    std::ostream& operator<<(std::ostream& o, const Element& e)
    {
        o << e.to_str();
        return o;
    }
};
<|endoftext|>


<commit_before>#ifndef __VECTOR_2D__
#define __VECTOR_2D__

// 	Copyright (C) Kevin Suffern 2000-2007.
//	This C++ code is for non-commercial purposes only.
//	This C++ code is licensed under the GNU General Public License Version 2.
//	See the file COPYING.txt for the full license.

#include "Matrix.h"

class Normal;
class Point2D;

//----------------------------------------- class Vector2D

class Vector2D {
	public:

		double	x, y;

	public:

		Vector2D(void);											// default constructor
		Vector2D(double a);										// constructor
		Vector2D(double _x, double _y);				// constructor
		Vector2D(const Vector2D& v);							// copy constructor
		Vector2D(const Normal& n);								// constructs a vector from a Normal
		Vector2D(const Point2D& p);								// constructs a vector from a point

		~Vector2D (void);										// destructor

		Vector2D& 												// assignment operator
		operator= (const Vector2D& rhs);

		Vector2D& 												// assign a Normal to a vector
		operator= (const Normal& rhs);

		Vector2D& 												// assign a Point2D to a vector
		operator= (const Point2D& rhs);

		Vector2D												// unary minus
		operator- (void) const;

		double													// length
		length(void);

		double													// square of the length
		len_squared(void);

		Vector2D												// multiplication by a double on the right
		operator* (const double a) const;

		Vector2D												// division by a double
		operator/ (const double a) const;

		Vector2D												// addition
		operator+ (const Vector2D& v) const;

		Vector2D& 												// compound addition
		operator+= (const Vector2D& v);

		Vector2D												// subtraction
		operator- (const Vector2D& v) const;

		double 													// dot product
		operator* (const Vector2D& b) const;

		Vector2D 												// cross product
		operator^ (const Vector2D& v) const;

		void 													// convert vector to a unit vector
		normalize(void);

		Vector2D& 												// return a unit vector, and normalize the vector
		hat(void);
};

// inlined member functions

// ------------------------------------------------------------------------ unary minus
// this does not change the current vector
// this allows ShadeRec objects to be declared as constant arguments in many shading
// functions that reverse the direction of a ray that's stored in the ShadeRec object

inline Vector2D
Vector2D::operator- (void) const {
	return (Vector2D(-x, -y));
}

// ---------------------------------------------------------------------  len_squared
// the square of the length

inline double
Vector2D::len_squared(void) {
	return (x * x + y * y);
}

// ----------------------------------------------------------------------- operator*
// multiplication by a double on the right

inline Vector2D
Vector2D::operator* (const double a) const {
	return (Vector2D(x * a, y * a));
}

// ----------------------------------------------------------------------- operator/
// division by a double

inline Vector2D
Vector2D::operator/ (const double a) const {
	return (Vector2D(x / a, y / a));
}

// ----------------------------------------------------------------------- operator+
// addition

inline Vector2D
Vector2D::operator+ (const Vector2D& v) const {
	return (Vector2D(x + v.x, y + v.y));
}

// ----------------------------------------------------------------------- operator-
// subtraction

inline Vector2D
Vector2D::operator- (const Vector2D& v) const {
	return (Vector2D(x - v.x, y - v.y));
}

// ----------------------------------------------------------------------- operator*
// dot product

inline double
Vector2D::operator* (const Vector2D& v) const {
	return (x * v.x + y * v.y);
}

// ----------------------------------------------------------------------- operator^
// cross product

inline Vector2D
Vector2D::operator^ (const Vector2D& v) const {
	return (Vector2D(x * v.y - y * v.x));
}

// ---------------------------------------------------------------------  operator+=
// compound addition

inline Vector2D&
Vector2D::operator+= (const Vector2D& v) {
	x += v.x; y += v.y;
	return (*this);
}

// inlined non-member function

// ----------------------------------------------------------------------- operator*
// multiplication by a double on the left

Vector2D 											// prototype
operator* (const double a, const Vector2D& v);

inline Vector2D
operator* (const double a, const Vector2D& v) {
	return (Vector2D(a * v.x, a * v.y));
}

#endif

<commit_msg>Deleted unused matrix class<commit_after>#ifndef __VECTOR_2D__
#define __VECTOR_2D__

// 	Copyright (C) Kevin Suffern 2000-2007.
//	This C++ code is for non-commercial purposes only.
//	This C++ code is licensed under the GNU General Public License Version 2.
//	See the file COPYING.txt for the full license.

class Normal;
class Point2D;

//----------------------------------------- class Vector2D

class Vector2D {
	public:

		double	x, y;

	public:

		Vector2D(void);											// default constructor
		Vector2D(double a);										// constructor
		Vector2D(double _x, double _y);				// constructor
		Vector2D(const Vector2D& v);							// copy constructor
		Vector2D(const Normal& n);								// constructs a vector from a Normal
		Vector2D(const Point2D& p);								// constructs a vector from a point

		~Vector2D (void);										// destructor

		Vector2D& 												// assignment operator
		operator= (const Vector2D& rhs);

		Vector2D& 												// assign a Normal to a vector
		operator= (const Normal& rhs);

		Vector2D& 												// assign a Point2D to a vector
		operator= (const Point2D& rhs);

		Vector2D												// unary minus
		operator- (void) const;

		double													// length
		length(void);

		double													// square of the length
		len_squared(void);

		Vector2D												// multiplication by a double on the right
		operator* (const double a) const;

		Vector2D												// division by a double
		operator/ (const double a) const;

		Vector2D												// addition
		operator+ (const Vector2D& v) const;

		Vector2D& 												// compound addition
		operator+= (const Vector2D& v);

		Vector2D												// subtraction
		operator- (const Vector2D& v) const;

		double 													// dot product
		operator* (const Vector2D& b) const;

		Vector2D 												// cross product
		operator^ (const Vector2D& v) const;

		void 													// convert vector to a unit vector
		normalize(void);

		Vector2D& 												// return a unit vector, and normalize the vector
		hat(void);
};

// inlined member functions

// ------------------------------------------------------------------------ unary minus
// this does not change the current vector
// this allows ShadeRec objects to be declared as constant arguments in many shading
// functions that reverse the direction of a ray that's stored in the ShadeRec object

inline Vector2D
Vector2D::operator- (void) const {
	return (Vector2D(-x, -y));
}

// ---------------------------------------------------------------------  len_squared
// the square of the length

inline double
Vector2D::len_squared(void) {
	return (x * x + y * y);
}

// ----------------------------------------------------------------------- operator*
// multiplication by a double on the right

inline Vector2D
Vector2D::operator* (const double a) const {
	return (Vector2D(x * a, y * a));
}

// ----------------------------------------------------------------------- operator/
// division by a double

inline Vector2D
Vector2D::operator/ (const double a) const {
	return (Vector2D(x / a, y / a));
}

// ----------------------------------------------------------------------- operator+
// addition

inline Vector2D
Vector2D::operator+ (const Vector2D& v) const {
	return (Vector2D(x + v.x, y + v.y));
}

// ----------------------------------------------------------------------- operator-
// subtraction

inline Vector2D
Vector2D::operator- (const Vector2D& v) const {
	return (Vector2D(x - v.x, y - v.y));
}

// ----------------------------------------------------------------------- operator*
// dot product

inline double
Vector2D::operator* (const Vector2D& v) const {
	return (x * v.x + y * v.y);
}

// ----------------------------------------------------------------------- operator^
// cross product

inline Vector2D
Vector2D::operator^ (const Vector2D& v) const {
	return (Vector2D(x * v.y - y * v.x));
}

// ---------------------------------------------------------------------  operator+=
// compound addition

inline Vector2D&
Vector2D::operator+= (const Vector2D& v) {
	x += v.x; y += v.y;
	return (*this);
}

// inlined non-member function

// ----------------------------------------------------------------------- operator*
// multiplication by a double on the left

Vector2D 											// prototype
operator* (const double a, const Vector2D& v);

inline Vector2D
operator* (const double a, const Vector2D& v) {
	return (Vector2D(a * v.x, a * v.y));
}

#endif

<|endoftext|>