Add files

This commit is contained in:
2025-01-14 01:15:48 +01:00
commit 2f9fcec55b
406 changed files with 87154 additions and 0 deletions

View File

@@ -0,0 +1,130 @@
//This file is part of Bertini 2.
//
//configured.hpp is free software: you can redistribute it and/or modify
//it under the terms of the GNU General Public License as published by
//the Free Software Foundation, either version 3 of the License, or
//(at your option) any later version.
//
//configured.hpp 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 General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with configured.hpp. If not, see <http://www.gnu.org/licenses/>.
//
// Copyright(C) 2016 - 2021 by Bertini2 Development Team
//
// See <http://www.gnu.org/licenses/> for a copy of the license,
// as well as COPYING. Bertini2 is provided with permitted
// additional terms in the b2/licenses/ directory.
// individual authors of this file include:
// silviana amethyst, university of wisconsin-eau claire
//
// detail/configured.hpp
/**
\file detail/configured.hpp
\brief Contains the detail/configured helper type, for templated getting/setting/storage of config structs
*/
#pragma once
#include "bertini2/detail/is_template_parameter.hpp"
namespace bertini {
namespace detail{
/**
This templated struct allows one to provide a variable typelist of config structs (or anything else for that matter), and provides a way to get and set these configs by looking up the structs by type.
I will add lookup by index if it is needed. If you need to look up by index, try type first. If your types are non-unique, consider making a struct to hold the things you are storing.
## On nested configs. If two or more things in your inheritance tree require Configured,
consider the following code, which can help determine whether to Get or Set from here, or to pass
down the tree to a base class.
\code
template <typename T>
const
typename std::enable_if<detail::IsTemplateParameter<T, config::Cauchy<typename TrackerTraits<TrackerType>::BaseRealType>>::value, T>::type
& Get() const
{
return Config::template Get<T>();
}
template <typename T>
const
typename std::enable_if<not detail::IsTemplateParameter<T, config::Cauchy<typename TrackerTraits<TrackerType>::BaseRealType>>::value, T>::type
& Get() const
{
return EndgameBase<TrackerType, FinalEGT, UsedNumTs...>::template Get<T>();
}
template <typename T>
typename std::enable_if<detail::IsTemplateParameter<T, config::Cauchy<typename TrackerTraits<TrackerType>::BaseRealType>>::value, void>::type
Set(T const& t)
{
Config::template Set(t);
}
template <typename T>
typename std::enable_if<not detail::IsTemplateParameter<T, config::Cauchy<typename TrackerTraits<TrackerType>::BaseRealType>>::value, void>::type
Set(T const& t)
{
EndgameBase<TrackerType, FinalEGT, UsedNumTs...>::template Set(t);
}
\endcode
*/
template<typename ...Ts>
struct Configured
{
std::tuple<Ts...> configuration_;
template<typename ... T>
Configured(T const& ...t) : configuration_(t...)
{}
template<typename T, typename = typename std::enable_if<IsTemplateParameter<T,Ts...>::value>::type>
const T& Get() const
{
return std::get<T>(configuration_);
}
template<typename T, typename = typename std::enable_if<IsTemplateParameter<T,Ts...>::value>::type>
void Set(T const& t)
{
std::get<T>(configuration_) = t;
}
using UsedConfigs = TypeList<Ts...>;
}; // Configured
template<typename ...Ts>
struct Configured<TypeList<Ts...>> : public Configured<Ts...>
{
template<typename ... T>
Configured(T const& ...t) : Configured<Ts...>(t...)
{}
Configured() : Configured<Ts...>() {}
};
#define FORWARD_GET_CONFIGURED \
template <typename T> \
const T& Get() const \
{ return Config::template Get<T>();}
} // namespace detail
}

View File

@@ -0,0 +1,141 @@
//This file is part of Bertini 2.
//
//enable_permuted_arguments.hpp is free software: you can redistribute it and/or modify
//it under the terms of the GNU General Public License as published by
//the Free Software Foundation, either version 3 of the License, or
//(at your option) any later version.
//
//enable_permuted_arguments.hpp 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 General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with enable_permuted_arguments.hpp. If not, see <http://www.gnu.org/licenses/>.
//
// Copyright(C) 2015 - 2021 by Bertini2 Development Team
//
// See <http://www.gnu.org/licenses/> for a copy of the license,
// as well as COPYING. Bertini2 is provided with permitted
// additional terms in the b2/licenses/ directory.
// individual authors of this file include:
// silviana amethyst, university of wisconsin eau claire
// additionally, this file contains code
// based on and refined from SO post
// https://stackoverflow.com/questions/19329297/constructor-permutations-for-passing-parameters-in-arbitrary-order
// by user Daniel Frey.
/**
\file enable_permuted_arguments.hpp
Contains helper templates, based on and refined from SO post
https://stackoverflow.com/questions/19329297/constructor-permutations-for-passing-parameters-in-arbitrary-order
by user Daniel Frey.
*/
#ifndef BERTINI_ENABLE_PERMUTED_ARGUMENTS
#define BERTINI_ENABLE_PERMUTED_ARGUMENTS
#include <type_traits>
#include <tuple>
namespace bertini {
namespace detail {
// find the index of a type in a list of types,
// return sizeof...(Remaining) if T is not found
template< typename T, typename... Remaining >
struct IndexByType : std::integral_constant< std::size_t, 0 >
{};
// template specialization, enforcing the equality of the number of variadic arguments, and the corresponding index.
// if two types are the same, this template will be preferred since it's a closer match, and the static_assert will fail, preventing compilation.
template< typename T, typename... RemainingT >
struct IndexByType< T, T, RemainingT... > : std::integral_constant< std::size_t, 0 >
{
static_assert( IndexByType< T, RemainingT... >::value == sizeof...( RemainingT ), "No duplicates are allowed when enabling permuted arguments" );
};
// template specialization on two types. looks for the index of T in the latter arguments. If T1==T2, this template will not be used, but instead the above will.
template< typename T1, typename T2, typename... RemainingT >
struct IndexByType< T1, T2, RemainingT... > : std::integral_constant< std::size_t, IndexByType< T1, RemainingT... >::value + 1 >
{};
// a free function which gets a type from a tuple with no duplicates. Remember, duplicates are not allowed.
template< std::size_t I, std::size_t J,
typename T, typename... PresentT, typename... GivenT >
auto GetByIndex( const std::tuple< PresentT... >&,
const std::tuple< GivenT... >& absent_args )
-> typename std::enable_if< I == sizeof...( PresentT ), const T& >::type
{
return std::get< J >( absent_args );
}
// the other half of the get by index function
template< std::size_t I, std::size_t J,
typename T, typename... PresentT, typename... GivenT >
auto GetByIndex(const std::tuple< PresentT... >& present_args,
const std::tuple< GivenT... >& ) // these arguments will have to be default constructed
-> typename std::enable_if< I != sizeof...( PresentT ), const T& >::type /* remember, `I != sizeof...( PresentT )` means it found T in PresentT */
{
return std::get< I >( present_args );
}
// helper to validate that all Us are in Ts...
template< bool > struct AreValidArguments;
// the false one is never instantiated, so the 'false' template parameter will fail, deliberately
template<> struct AreValidArguments< true > : std::true_type
{};
// a proxy function which to ensure that the types are distinct, and that we can indeed get the index by type.
template< std::size_t... >
void ValidateTypes()
{}
// default construct the objects not present in the arguments, but required by the unpermute function
template< typename T >
struct DefaultConstruct
{ static const T value; };
template< typename T >
const T DefaultConstruct< T >::value
{};
} // namespace detail
// helper template which reorders parameters
template< typename... UnpermutedT, // these must be declared when using the function
typename... PermutedPresentT > // these are inferred, cannot be declared
std::tuple< const UnpermutedT&... > Unpermute( const PermutedPresentT&... present_permuted_args )
{
using namespace detail;
auto present_args = std::tie( present_permuted_args... );
auto absent_args = std::tie( DefaultConstruct< UnpermutedT >::value... );
//next we validate that the input arguments are valid for unpermuting. must have all distinct types.
ValidateTypes< AreValidArguments< IndexByType< const PermutedPresentT&,
const UnpermutedT&... >::value != sizeof...( UnpermutedT )
>::value...
>(); // this will fail if AreValidArguments are not valid ('true')
// finally, we return a tie of the unpermuted types, default constructed if necessary
return std::tie( GetByIndex< IndexByType< const UnpermutedT&, const PermutedPresentT&... >::value,
IndexByType< const UnpermutedT&, const UnpermutedT&... >::value, UnpermutedT >
( present_args, absent_args )... );
}
} // re: namespace bertini
#endif

View File

@@ -0,0 +1,165 @@
//This file is part of Bertini 2.
//
//events.hpp is free software: you can redistribute it and/or modify
//it under the terms of the GNU General Public License as published by
//the Free Software Foundation, either version 3 of the License, or
//(at your option) any later version.
//
//events.hpp 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 General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with events.hpp. If not, see <http://www.gnu.org/licenses/>.
//
// Copyright(C) 2015 - 2021 by Bertini2 Development Team
//
// See <http://www.gnu.org/licenses/> for a copy of the license,
// as well as COPYING. Bertini2 is provided with permitted
// additional terms in the b2/licenses/ directory.
// individual authors of this file include:
// silviana amethyst, university of wisconsin-eau claire
//
// detail/events.hpp
/**
\file detail/events.hpp
\brief Contains the detail/events base types
*/
#ifndef BERTINI_DETAIL_EVENTS_HPP
#define BERTINI_DETAIL_EVENTS_HPP
#include <boost/type_index.hpp>
namespace bertini {
/**
\brief Strawman Event type, enabling polymorphism.
This class is abstract, and should never actually be created.
*/
class AnyEvent
{ BOOST_TYPE_INDEX_REGISTER_CLASS
public:
virtual ~AnyEvent() = default;
};
template<class ObsT, bool IsConst = true>
class Event;
/**
\brief For emission of events from observables.
An observable object probably wants to emit events to notify observers that things are happening. The observers filter the events, at this time by dynamic casting (slow, I know, but it works for now. Premature optimization, etc.) A better method than dynamic casting would be to filter based on a union of bits or something. If you, the reader, want to help make this better, please contact a developer!
Say I am an observable object, and I want to emit an event. Events attach the type of object emitting them, and in fact (a refence to) the emitter itself. So if my type is `T`, I would do something like `NotifyObservers(Event<T>(*this))`. Then an Observer can filter based on a heirarchy of event types, etc.
\tparam ObsT The Observed type. When emitting an event, you pass in the type of object emitting the event, and the object itself. Then the observer can `Get` the emitting object, and do (const) stuff to it.
\see Observable, Observable::NotifyObservers, ADD_BERTINI_EVENT_TYPE, AMPPathAccumulator, AnyEvent
*/
template<class ObsT>
class Event<ObsT, true> : public AnyEvent
{ BOOST_TYPE_INDEX_REGISTER_CLASS
public:
/**
\brief Constructor for an event.
\param obs The observable emitting the event to observers. Passed by const reference, this permits arbitrary `const` function calls by the observer.
*/
Event(ObsT const& obs) : current_observable_(obs)
{}
virtual ~Event() = default;
/**
\brief Get the emitting object, by `const` reference.
\return The observable who emitted the event. This permits calls of arbitrary const functions, particularly getters.
\see AMPPathAccumulator for simple example of filtering using `dynamic_cast`s
*/
ObsT const& Get() const
{return current_observable_;}
Event() = delete;
using HeldT = const ObsT&;
protected:
const ObsT& current_observable_;
};
/**
\brief For emission of events from observables.
An observable object probably wants to emit events to notify observers that things are happening. The observers filter the events, at this time by dynamic casting (slow, I know, but it works for now. Premature optimization, etc.) A better method than dynamic casting would be to filter based on a union of bits or something. If you, the reader, want to help make this better, please contact a developer!
Say I am an observable object, and I want to emit an event. Events attach the type of object emitting them, and in fact (a refence to) the emitter itself. So if my type is `T`, I would do something like `NotifyObservers(Event<T>(*this))`. Then an Observer can filter based on a heirarchy of event types, etc.
\tparam ObsT The Observed type. When emitting an event, you pass in the type of object emitting the event, and the object itself. Then the observer can `Get` the emitting object, and do (const) stuff to it.
\see Observable, Observable::NotifyObservers, ADD_BERTINI_EVENT_TYPE, AMPPathAccumulator, AnyEvent
*/
template<class ObsT>
class Event<ObsT,false> : public AnyEvent
{ BOOST_TYPE_INDEX_REGISTER_CLASS
public:
/**
\brief Constructor for an event.
\param obs The observable emitting the event to observers. Passed by const reference, this permits arbitrary `const` function calls by the observer.
*/
Event(ObsT & obs) : current_observable_(obs)
{}
virtual ~Event() = default;
/**
\brief Get the emitting object, by `const` reference.
\return The observable who emitted the event. This permits calls of arbitrary const functions, particularly getters.
\see AMPPathAccumulator for simple example of filtering using `dynamic_cast`s
*/
ObsT & Get()
{return current_observable_;}
Event() = delete;
using HeldT = ObsT&;
protected:
ObsT& current_observable_;
};
template<typename ObsT>
using ConstEvent = Event<ObsT,true>;
template<typename ObsT>
using MutableEvent = Event<ObsT,false>;
/**
\brief Defines a new event type in a hierarchy
\param event_name The name of the new Event type you are making.
\param event_parenttype The name of the parent Event type in the heirarchy.
*/
#define ADD_BERTINI_EVENT_TYPE(event_name,event_parenttype) template<class ObservedT> \
class event_name : public event_parenttype<ObservedT> \
{ BOOST_TYPE_INDEX_REGISTER_CLASS \
public: \
using HeldT = typename event_parenttype<ObservedT>::HeldT; \
event_name(HeldT obs) : event_parenttype<ObservedT>(obs){} \
virtual ~event_name() = default; \
event_name() = delete; }
} //re: namespace bertini
#endif

View File

@@ -0,0 +1,72 @@
//This file is part of Bertini 2.
//
//is_template_parameter.hpp is free software: you can redistribute it and/or modify
//it under the terms of the GNU General Public License as published by
//the Free Software Foundation, either version 3 of the License, or
//(at your option) any later version.
//
//is_template_parameter.hpp 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 General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with is_template_parameter.hpp. If not, see <http://www.gnu.org/licenses/>.
//
// Copyright(C) 2015 - 2021 by Bertini2 Development Team
//
// See <http://www.gnu.org/licenses/> for a copy of the license,
// as well as COPYING. Bertini2 is provided with permitted
// additional terms in the b2/licenses/ directory.
// individual authors of this file include:
// silviana amethyst, university of wisconsin-eau claire
//
// detail/is_template_parameter.hpp
/**
\file detail/is_template_parameter.hpp
\brief Contains the detail/is_template_parameter helper, for checking whether a type is a template parameter in a variable template
*/
#pragma once
#include "bertini2/detail/typelist.hpp"
namespace bertini {
namespace detail{
/**
Base template, which says 'no', it's not in the pack.
*/
template <typename...>
struct IsTemplateParameter {
static constexpr bool value = false;
};
/**
Specialized template, which says 'yes', if it is in the pack, by recursively expanding the pack.
*/
template <typename F, typename S, typename... T>
struct IsTemplateParameter<F, S, T...> {
static constexpr bool value =
std::is_same<F, S>::value || IsTemplateParameter<F, T...>::value;
// either it is the same as the first one in the pack, or we need to expand to the right in the pack.
};
template < typename T, typename ...Ts>
struct IsTemplateParameter<T, TypeList<Ts...>>
{
static constexpr bool value = IsTemplateParameter<T, Ts...>::value;
};
} // namespace detail
}

View File

@@ -0,0 +1,115 @@
//This file is part of Bertini 2.
//
//bertini2/detail/observable.hpp is free software: you can redistribute it and/or modify
//it under the terms of the GNU General Public License as published by
//the Free Software Foundation, either version 3 of the License, or
//(at your option) any later version.
//
//bertini2/detail/observable.hpp 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 General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with bertini2/detail/observable.hpp. If not, see <http://www.gnu.org/licenses/>.
//
// Copyright(C) 2015 - 2021 by Bertini2 Development Team
//
// See <http://www.gnu.org/licenses/> for a copy of the license,
// as well as COPYING. Bertini2 is provided with permitted
// additional terms in the b2/licenses/ directory.
// individual authors of this file include:
// silviana amethyst, university of wisconsin-eau claire
//
/**
\file bertini2/detail/observable.hpp
\brief Contains the observable base types
*/
#ifndef BERTINI_DETAIL_OBSERVABLE_HPP
#define BERTINI_DETAIL_OBSERVABLE_HPP
#include "bertini2/detail/observer.hpp"
#include "bertini2/detail/events.hpp"
namespace bertini{
/**
\brief An abstract observable type, maintaining a list of observers, who can be notified in case of Events.
Some known observable types are Tracker and Endgame.
*/
class Observable
{
public:
virtual ~Observable() = default;
/**
\brief Add an observer, to observe this observable.
*/
void AddObserver(AnyObserver& new_observer) const
{
if (find_if(begin(current_watchers_), end(current_watchers_), [&](const auto& held_obs)
{ return &held_obs.get() == &new_observer; })==end(current_watchers_))
current_watchers_.push_back(std::ref(new_observer));
}
/**
\brief Remove an observer from this observable.
*/
void RemoveObserver(AnyObserver& observer) const
{
auto new_end = std::remove_if(current_watchers_.begin(), current_watchers_.end(),
[&](const auto& held_obs)
{ return &held_obs.get() == &observer; });
current_watchers_.erase(new_end, current_watchers_.end());
// current_watchers_.erase(std::remove(current_watchers_.begin(), current_watchers_.end(), std::ref(observer)), current_watchers_.end());
}
protected:
/**
\brief Sends an Event (more particularly, AnyEvent) to all watching observers of this object.
This function could potentially be improved by filtering on the observer's desired event types, if known at compile time. This could potentially be a performance bottleneck (hopefully not!) since filtering can use `dynamic_cast`ing. One hopes this cost is overwhelmed by things like linear algebra and system evaluation.
\param e The event to emit. Its type should be derived from AnyEvent.
*/
void NotifyObservers(AnyEvent const& e) const
{
for (auto& obs : current_watchers_)
obs.get().Observe(e);
}
void NotifyObservers(AnyEvent & e) const
{
for (auto& obs : current_watchers_)
obs.get().Observe(e);
}
private:
using ObserverContainer = std::vector<std::reference_wrapper<AnyObserver>>;
mutable ObserverContainer current_watchers_;
};
} // namespace bertini
#endif

View File

@@ -0,0 +1,123 @@
//This file is part of Bertini 2.
//
//bertini2/detail/observer.hpp is free software: you can redistribute it and/or modify
//it under the terms of the GNU General Public License as published by
//the Free Software Foundation, either version 3 of the License, or
//(at your option) any later version.
//
//bertini2/detail/observer.hpp 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 General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with bertini2/detail/observer.hpp. If not, see <http://www.gnu.org/licenses/>.
//
// Copyright(C) 2015 - 2021 by Bertini2 Development Team
//
// See <http://www.gnu.org/licenses/> for a copy of the license,
// as well as COPYING. Bertini2 is provided with permitted
// additional terms in the b2/licenses/ directory.
// individual authors of this file include:
// silviana amethyst, university of wisconsin-eau claire
//
/**
\file bertini2/detail/observer.hpp
\brief Contains the observer base types.
*/
#ifndef BERTINI_DETAIL_OBSERVER_HPP
#define BERTINI_DETAIL_OBSERVER_HPP
#include <tuple>
#include <utility>
#include <boost/fusion/adapted/std_tuple.hpp>
#include <boost/fusion/algorithm/iteration/for_each.hpp>
#include <boost/fusion/include/for_each.hpp>
#include "bertini2/detail/events.hpp"
namespace bertini{
/**
\brief Strawman base class for Observer objects.
\see Observer
*/
class AnyObserver
{ BOOST_TYPE_INDEX_REGISTER_CLASS
public:
virtual ~AnyObserver() = default;
/**
\brief Observe the observable object being observed. This is probably in response to NotifyObservers.
This virtual function must be overridden by actual observers, defining how they observe the observable they are observing, probably filtering events and doing something specific for different ones.
\param e The event which was emitted by the observed object.
*/
virtual void Observe(AnyEvent const& e) = 0;
};
/**
\brief Actual observer type, which you should derive from to extract custom information from observable types.
\tparam ObservedT The type of object the observer observes.
\tparam RetT The type of object the observer returns when it visits.
\see PrecisionAccumulator, GoryDetailLogger, MultiObserver
*/
template<class ObservedT>
class Observer : public AnyObserver
{ BOOST_TYPE_INDEX_REGISTER_CLASS
public:
virtual ~Observer() = default;
};
/**
\brief A class which can glob together observer types into a new, single observer type.
If there are pre-existing observers for the object you wish to observe, rather than making one of each, and attaching each to the observable, you can make many things one.
https://frinkiac.com/?q=many%20guns%20into%20five
\tparam ObservedT The type of thing the observer types you are gluing together observe. They must all observe the same type of object.
\tparam ObserverTypes The already-existing observer types you are gluing together. You can put as many of them together as you want!
*/
template<class ObservedT, template<class> class... ObserverTypes>
class MultiObserver : public Observer<ObservedT>
{ BOOST_TYPE_INDEX_REGISTER_CLASS
public:
/**
\brief Observe override which calls the overrides for the types you glued together.
\param e The emitted event which caused observation.
*/
void Observe(AnyEvent const& e) override
{
using namespace boost::fusion;
auto f = [&e](auto &obs) { obs.Observe(e); };
for_each(observers_, f);
}
std::tuple<ObserverTypes<ObservedT>...> observers_;
virtual ~MultiObserver() = default;
};
}
#endif

View File

@@ -0,0 +1,62 @@
//This file is part of Bertini 2.
//
//bertini2/detail/singleton.hpp is free software: you can redistribute it and/or modify
//it under the terms of the GNU General Public License as published by
//the Free Software Foundation, either version 3 of the License, or
//(at your option) any later version.
//
//bertini2/detail/singleton.hpp 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 General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with bertini2/detail/singleton.hpp. If not, see <http://www.gnu.org/licenses/>.
//
// Copyright(C) 2021 by Bertini2 Development Team
//
// See <http://www.gnu.org/licenses/> for a copy of the license,
// as well as COPYING. Bertini2 is provided with permitted
// additional terms in the b2/licenses/ directory.
/**
\file bertini2/detail/singleton.hpp
\brief Provides types and utilities for dealing with global defaults for the detail routines
*/
#pragma once
namespace bertini{
namespace detail{
/**
\brief A virtual singleton base class which can be used in a heirarchy to require a class to be singleton.
\note
This class is virtual, so make sure you mark destructors as virtual.
*/
struct Singleton {
virtual ~Singleton() = default;
private:
// mark both the default and copy constructor as private
Singleton(){}
Singleton(Singleton const&){}
};
} // namespace detail
} // namespace bertini

View File

@@ -0,0 +1,98 @@
//This file is part of Bertini 2.
//
//typelist.hpp is free software: you can redistribute it and/or modify
//it under the terms of the GNU General Public License as published by
//the Free Software Foundation, either version 3 of the License, or
//(at your option) any later version.
//
//typelist.hpp 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 General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with typelist.hpp. If not, see <http://www.gnu.org/licenses/>.
//
// Copyright(C) 2021 by Bertini2 Development Team
//
// See <http://www.gnu.org/licenses/> for a copy of the license,
// as well as COPYING. Bertini2 is provided with permitted
// additional terms in the b2/licenses/ directory.
// individual authors of this file include:
// silviana amethyst, university of wisconsin-eau claire
/**
\file detail/typelist.hpp
\brief Contains the detail/typelist helper type, for templated getting/setting/storage of config structs
*/
#pragma once
#include "bertini2/detail/enable_permuted_arguments.hpp"
#include "bertini2/eigen_extensions.hpp"
namespace bertini {
namespace detail {
/**
\brief A basic typelist, in the style of Modern C++ Design, but using variadic templates
To construct one, feed the types you want into the template arguments of the TypeList
*/
template <typename... Ts>
struct TypeList {
using ToTuple = std::tuple<Ts...>;
using ToTupleOfVec = std::tuple<Vec<Ts>...>;
using ToTupleOfReal = std::tuple<typename Eigen::NumTraits<Ts>::Real...>;
template <template<typename> class ContT>
using ToTupleOfCont = std::tuple<ContT<Ts>...>;
template<typename ...Rs>
static
std::tuple<Ts...> Unpermute(const Rs& ...rs)
{
return bertini::Unpermute<Ts...>(rs...);
}
};
/**
\brief Concatenate two typelists
Get resulting TypeList via something like `ListCat< TypeList<int>,TypeList<double> >::type`
*/
template <typename ...Ts>
struct ListCat {};
/**
\brief A specialization of ListCat for joining two lists
*/
template <typename ...Ts, typename ... Rs>
struct ListCat <TypeList<Ts...>, TypeList<Rs...>>
{
using type = TypeList<Ts..., Rs...>;
};
/**
\brief A specialization of ListCat for joining 3+ lists
This specialization works via recursion
*/
template <typename ...Ps, typename ... Qs, typename ... Rs>
struct ListCat <TypeList<Ps...>, TypeList<Qs...>, TypeList<Rs...>>
{
using type = TypeList<Ps..., Qs..., Rs...>;
};
}} // close namespaces

View File

@@ -0,0 +1,129 @@
//This file is part of Bertini 2.
//
//visitable.hpp is free software: you can redistribute it and/or modify
//it under the terms of the GNU General Public License as published by
//the Free Software Foundation, either version 3 of the License, or
//(at your option) any later version.
//
//visitable.hpp 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 General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with visitable.hpp. If not, see <http://www.gnu.org/licenses/>.
//
// Copyright(C) 2015 - 2021 by Bertini2 Development Team
//
// See <http://www.gnu.org/licenses/> for a copy of the license,
// as well as COPYING. Bertini2 is provided with permitted
// additional terms in the b2/licenses/ directory.
// individual authors of this file include:
// silviana amethyst, university of wisconsin-eau claire
//
/**
\file visitable.hpp
\brief Contains the visitable base types
*/
#ifndef BERTINI_DETAIL_VISITABLE_HPP
#define BERTINI_DETAIL_VISITABLE_HPP
#include "bertini2/detail/visitor.hpp"
#include "bertini2/detail/events.hpp"
namespace bertini{
namespace policy{
/**
\brief A policy for what to do when a visited type is encoutered by a visitor it doesn't know.
Defines the default behaviour when an unknown visitor is encountered during visitation.
Assumes the return type is default constructible.
*/
template<class VisitedT, typename RetT>
struct DefaultConstruct
{
static RetT OnUnknownVisitor(VisitedT&a, VisitorBase&) // VisitorBase is inherited from using CRTP -- it's not a template parameter to this function, so its typeid name is useless.
{
std::cout << "unknown visitor: " << a << " of type " << typeid(VisitedT).name() << ". Make sure you've added it in all three places! two in the class definition (type inheritance listing as visiting, and virtual function declaration), and one in cpp source (function definition)." << std::endl;
return VisitedT();
}
};
template<class VisitedT, typename RetT>
struct RaiseExceptionWithTypeNamesInMessage
{
static RetT OnUnknownVisitor(VisitedT&a, VisitorBase&)
{
std::stringstream err_msg;
err_msg << "unknown visitor: " << a << " of type " << typeid(VisitedT).name() << ". Make sure you've added it in all three places! two in the class definition (type inheritance listing as visiting, and virtual function declaration), and one in cpp source (function definition)." << std::endl;
throw std::runtime_error(err_msg.str());
}
};
/**
The default policy for what to do when a visitable is visited by an unknown visitor.
*/
template<class VisitedT, typename RetT>
using DefaultCatchAll = RaiseExceptionWithTypeNamesInMessage<VisitedT, RetT>;
} // namespace policy
/**
\brief The base class for visitable types.
Implemented based on Alexandrescu, 2001, and Hythem Sidky's SAPHRON package, with his permission.
\see BERTINI_DEFAULT_VISITABLE
*/
template< typename RetT = void, template<class,class> class CatchAll = policy::DefaultCatchAll>
class VisitableBase
{
public:
typedef RetT VisitReturnType;
virtual ~VisitableBase() = default;
virtual VisitReturnType Accept(VisitorBase&) = 0; // the implementation will either be provided by a macro, or by hand, for each class which is visitable.
protected:
/**
\brief Abstract method for how to accept a visitor.
This function simply Forwards to the Visit method of the visitor, if the visitor's type is known. If known, invokes the behaviour defined by the CatchAll template parameter.
\tparam T The type of the visited object. Should be inferred by the compiler.
\param visited The visited visitable object.
\param guest The visiting object.
*/
template<typename T>
static
VisitReturnType AcceptBase(T& visited, VisitorBase& guest)
{
if (auto p = dynamic_cast<Visitor<T>*>(&guest))
return p->Visit(visited);
else
return CatchAll<T,RetT>::OnUnknownVisitor(visited, guest);
}
};
/**
\brief macro for classes which want default Accept implementation, having nothing fancy to do when accepting.
*/
#define BERTINI_DEFAULT_VISITABLE() \
virtual VisitReturnType Accept(VisitorBase& guest) override \
{ return AcceptBase(*this, guest); }
} // namespace bertini
#endif

View File

@@ -0,0 +1,73 @@
//This file is part of Bertini 2.
//
//visitor.hpp is free software: you can redistribute it and/or modify
//it under the terms of the GNU General Public License as published by
//the Free Software Foundation, either version 3 of the License, or
//(at your option) any later version.
//
//visitor.hpp 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 General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with visitor.hpp. If not, see <http://www.gnu.org/licenses/>.
//
// Copyright(C) 2015 - 2021 by Bertini2 Development Team
//
// See <http://www.gnu.org/licenses/> for a copy of the license,
// as well as COPYING. Bertini2 is provided with permitted
// additional terms in the b2/licenses/ directory.
// individual authors of this file include:
// silviana amethyst, university of wisconsin-eau claire
//
/**
\file visitor.hpp
\brief Contains the visitor base types.
*/
#ifndef BERTINI_DETAIL_VISITOR_HPP
#define BERTINI_DETAIL_VISITOR_HPP
#include <boost/type_index.hpp>
namespace bertini{
/**
\brief A strawman class for implementing the visitor pattern.
Deliberately empty, the non-base visitors must derive from it.
\see Visitor, Observer, AnyObserver, MultiObserver
*/
class VisitorBase
{ BOOST_TYPE_INDEX_REGISTER_CLASS
public:
virtual ~VisitorBase() = default;
};
/**
\brief The first non-trivial visitor class.
Derive from this when creating new visitor types.
\tparam VisitedT The type of object the visitor visits.
\tparam RetT The type of object to be returned when visiting. Default is `void`.
*/
template<class VisitedT, typename RetT = void>
class Visitor
{ BOOST_TYPE_INDEX_REGISTER_CLASS
public:
typedef RetT ReturnType;
virtual ReturnType Visit(VisitedT const &) = 0;
virtual ~Visitor() = default;
};
}
#endif