mirror of
https://github.com/boostorg/type_index.git
synced 2025-07-29 20:07:18 +02:00
Test and verify patches
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@ -374,4 +374,4 @@
|
||||
/more/
|
||||
/status/
|
||||
/tools/
|
||||
stage/
|
||||
/stage/
|
||||
|
5
patched/README.md
Normal file
5
patched/README.md
Normal file
@ -0,0 +1,5 @@
|
||||
patches for Boost libraries to work without RTTI
|
||||
==========
|
||||
|
||||
Here are the patches that are TESTED and work well with RTTI disabled and enabled.
|
||||
Patches add tests for some of the libraries to make sure that library compile and work without RTTI.
|
239
patched/any.hpp
239
patched/any.hpp
@ -1,239 +0,0 @@
|
||||
// See http://www.boost.org/libs/any for Documentation.
|
||||
|
||||
#ifndef BOOST_ANY_INCLUDED
|
||||
#define BOOST_ANY_INCLUDED
|
||||
|
||||
// what: variant type boost::any
|
||||
// who: contributed by Kevlin Henney,
|
||||
// with features contributed and bugs found by
|
||||
// Ed Brey, Mark Rodgers, Peter Dimov, and James Curran
|
||||
// when: July 2001
|
||||
// where: tested with BCC 5.5, MSVC 6.0, and g++ 2.95
|
||||
|
||||
#include <algorithm>
|
||||
#include <typeinfo>
|
||||
|
||||
#include "boost/config.hpp"
|
||||
#include <boost/type_traits/remove_reference.hpp>
|
||||
#include <boost/type_traits/is_reference.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/type_index.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
class any
|
||||
{
|
||||
public: // structors
|
||||
|
||||
any()
|
||||
: content(0)
|
||||
{
|
||||
}
|
||||
|
||||
template<typename ValueType>
|
||||
any(const ValueType & value)
|
||||
: content(new holder<ValueType>(value))
|
||||
{
|
||||
}
|
||||
|
||||
any(const any & other)
|
||||
: content(other.content ? other.content->clone() : 0)
|
||||
{
|
||||
}
|
||||
|
||||
~any()
|
||||
{
|
||||
delete content;
|
||||
}
|
||||
|
||||
public: // modifiers
|
||||
|
||||
any & swap(any & rhs)
|
||||
{
|
||||
std::swap(content, rhs.content);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename ValueType>
|
||||
any & operator=(const ValueType & rhs)
|
||||
{
|
||||
any(rhs).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
any & operator=(any rhs)
|
||||
{
|
||||
rhs.swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
public: // queries
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
return !content;
|
||||
}
|
||||
|
||||
type_index type() const
|
||||
{
|
||||
return content ? content->type() : type_id<void>();
|
||||
}
|
||||
|
||||
#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
|
||||
private: // types
|
||||
#else
|
||||
public: // types (public so any_cast can be non-friend)
|
||||
#endif
|
||||
|
||||
class placeholder
|
||||
{
|
||||
public: // structors
|
||||
|
||||
virtual ~placeholder()
|
||||
{
|
||||
}
|
||||
|
||||
public: // queries
|
||||
|
||||
virtual type_index type() const = 0;
|
||||
|
||||
virtual placeholder * clone() const = 0;
|
||||
|
||||
};
|
||||
|
||||
template<typename ValueType>
|
||||
class holder : public placeholder
|
||||
{
|
||||
public: // structors
|
||||
|
||||
holder(const ValueType & value)
|
||||
: held(value)
|
||||
{
|
||||
}
|
||||
|
||||
public: // queries
|
||||
|
||||
virtual type_index type() const
|
||||
{
|
||||
return type_id<ValueType>();
|
||||
}
|
||||
|
||||
virtual placeholder * clone() const
|
||||
{
|
||||
return new holder(held);
|
||||
}
|
||||
|
||||
public: // representation
|
||||
|
||||
ValueType held;
|
||||
|
||||
private: // intentionally left unimplemented
|
||||
holder & operator=(const holder &);
|
||||
};
|
||||
|
||||
#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
|
||||
|
||||
private: // representation
|
||||
|
||||
template<typename ValueType>
|
||||
friend ValueType * any_cast(any *);
|
||||
|
||||
template<typename ValueType>
|
||||
friend ValueType * unsafe_any_cast(any *);
|
||||
|
||||
#else
|
||||
|
||||
public: // representation (public so any_cast can be non-friend)
|
||||
|
||||
#endif
|
||||
|
||||
placeholder * content;
|
||||
|
||||
};
|
||||
|
||||
class bad_any_cast : public std::bad_cast
|
||||
{
|
||||
public:
|
||||
virtual const char * what() const throw()
|
||||
{
|
||||
return "boost::bad_any_cast: "
|
||||
"failed conversion using boost::any_cast";
|
||||
}
|
||||
};
|
||||
|
||||
template<typename ValueType>
|
||||
ValueType * any_cast(any * operand)
|
||||
{
|
||||
return operand &&
|
||||
operand->type() == type_id<ValueType>()
|
||||
? &static_cast<any::holder<ValueType> *>(operand->content)->held
|
||||
: 0;
|
||||
}
|
||||
|
||||
template<typename ValueType>
|
||||
inline const ValueType * any_cast(const any * operand)
|
||||
{
|
||||
return any_cast<ValueType>(const_cast<any *>(operand));
|
||||
}
|
||||
|
||||
template<typename ValueType>
|
||||
ValueType any_cast(any & operand)
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME remove_reference<ValueType>::type nonref;
|
||||
|
||||
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
// If 'nonref' is still reference type, it means the user has not
|
||||
// specialized 'remove_reference'.
|
||||
|
||||
// Please use BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION macro
|
||||
// to generate specialization of remove_reference for your class
|
||||
// See type traits library documentation for details
|
||||
BOOST_STATIC_ASSERT(!is_reference<nonref>::value);
|
||||
#endif
|
||||
|
||||
nonref * result = any_cast<nonref>(&operand);
|
||||
if(!result)
|
||||
boost::throw_exception(bad_any_cast());
|
||||
return *result;
|
||||
}
|
||||
|
||||
template<typename ValueType>
|
||||
inline ValueType any_cast(const any & operand)
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME remove_reference<ValueType>::type nonref;
|
||||
|
||||
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
// The comment in the above version of 'any_cast' explains when this
|
||||
// assert is fired and what to do.
|
||||
BOOST_STATIC_ASSERT(!is_reference<nonref>::value);
|
||||
#endif
|
||||
|
||||
return any_cast<const nonref &>(const_cast<any &>(operand));
|
||||
}
|
||||
|
||||
// Note: The "unsafe" versions of any_cast are not part of the
|
||||
// public interface and may be removed at any time. They are
|
||||
// required where we know what type is stored in the any and can't
|
||||
// use type_id<>() comparison, e.g., when our types may travel across
|
||||
// different shared libraries.
|
||||
template<typename ValueType>
|
||||
inline ValueType * unsafe_any_cast(any * operand)
|
||||
{
|
||||
return &static_cast<any::holder<ValueType> *>(operand->content)->held;
|
||||
}
|
||||
|
||||
template<typename ValueType>
|
||||
inline const ValueType * unsafe_any_cast(const any * operand)
|
||||
{
|
||||
return unsafe_any_cast<ValueType>(const_cast<any *>(operand));
|
||||
}
|
||||
}
|
||||
|
||||
// Copyright Kevlin Henney, 2000, 2001, 2002. All rights reserved.
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#endif
|
12
patched/any/Jamfile.patch
Normal file
12
patched/any/Jamfile.patch
Normal file
@ -0,0 +1,12 @@
|
||||
Index: .
|
||||
===================================================================
|
||||
--- . (revision 86520)
|
||||
+++ . (working copy)
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
test-suite any :
|
||||
[ run ../any_test.cpp ]
|
||||
+ [ run ../any_test.cpp : : : <rtti>off : testing_any_no_rtti ]
|
||||
[ run any_test_rv.cpp ]
|
||||
[ compile-fail any_cast_cv_failed.cpp ]
|
||||
[ compile-fail any_test_temporary_to_ref_failed.cpp ]
|
91
patched/any/any.patch
Normal file
91
patched/any/any.patch
Normal file
@ -0,0 +1,91 @@
|
||||
Index: .
|
||||
===================================================================
|
||||
--- . (revision 86520)
|
||||
+++ . (working copy)
|
||||
@@ -15,7 +15,7 @@
|
||||
// when: July 2001, April 2013 - May 2013
|
||||
|
||||
#include <algorithm>
|
||||
-#include <typeinfo>
|
||||
+#include <boost/type_index/type_info.hpp>
|
||||
|
||||
#include "boost/config.hpp"
|
||||
#include <boost/type_traits/remove_reference.hpp>
|
||||
@@ -29,17 +29,6 @@
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/type_traits/is_const.hpp>
|
||||
|
||||
-// See boost/python/type_id.hpp
|
||||
-// TODO: add BOOST_TYPEID_COMPARE_BY_NAME to config.hpp
|
||||
-# if defined(__GNUC__) \
|
||||
- || defined(_AIX) \
|
||||
- || ( defined(__sgi) && defined(__host_mips)) \
|
||||
- || (defined(__hpux) && defined(__HP_aCC)) \
|
||||
- || (defined(linux) && defined(__INTEL_COMPILER) && defined(__ICC))
|
||||
-# define BOOST_AUX_ANY_TYPE_ID_NAME
|
||||
-#include <cstring>
|
||||
-# endif
|
||||
-
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 4172) // Mistakenly warns: returning address of local variable or temporary
|
||||
@@ -149,9 +138,9 @@
|
||||
any().swap(*this);
|
||||
}
|
||||
|
||||
- const std::type_info & type() const BOOST_NOEXCEPT
|
||||
+ const boost::type_info & type() const BOOST_NOEXCEPT
|
||||
{
|
||||
- return content ? content->type() : typeid(void);
|
||||
+ return content ? content->type() : boost::type_id<void>();
|
||||
}
|
||||
|
||||
#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
|
||||
@@ -170,7 +159,7 @@
|
||||
|
||||
public: // queries
|
||||
|
||||
- virtual const std::type_info & type() const BOOST_NOEXCEPT = 0;
|
||||
+ virtual const boost::type_info & type() const BOOST_NOEXCEPT = 0;
|
||||
|
||||
virtual placeholder * clone() const = 0;
|
||||
|
||||
@@ -194,9 +183,9 @@
|
||||
#endif
|
||||
public: // queries
|
||||
|
||||
- virtual const std::type_info & type() const BOOST_NOEXCEPT
|
||||
+ virtual const boost::type_info & type() const BOOST_NOEXCEPT
|
||||
{
|
||||
- return typeid(ValueType);
|
||||
+ return boost::type_id<ValueType>();
|
||||
}
|
||||
|
||||
virtual placeholder * clone() const
|
||||
@@ -237,7 +226,12 @@
|
||||
lhs.swap(rhs);
|
||||
}
|
||||
|
||||
- class BOOST_SYMBOL_VISIBLE bad_any_cast : public std::bad_cast
|
||||
+ class BOOST_SYMBOL_VISIBLE bad_any_cast :
|
||||
+#ifndef BOOST_NO_RTTI
|
||||
+ public std::bad_cast
|
||||
+#else
|
||||
+ public std::exception
|
||||
+#endif
|
||||
{
|
||||
public:
|
||||
virtual const char * what() const BOOST_NOEXCEPT_OR_NOTHROW
|
||||
@@ -251,11 +245,7 @@
|
||||
ValueType * any_cast(any * operand) BOOST_NOEXCEPT
|
||||
{
|
||||
return operand &&
|
||||
-#ifdef BOOST_AUX_ANY_TYPE_ID_NAME
|
||||
- std::strcmp(operand->type().name(), typeid(ValueType).name()) == 0
|
||||
-#else
|
||||
- operand->type() == typeid(ValueType)
|
||||
-#endif
|
||||
+ operand->type() == boost::type_id<ValueType>()
|
||||
? &static_cast<any::holder<ValueType> *>(operand->content)->held
|
||||
: 0;
|
||||
}
|
61
patched/any/any_test.patch
Normal file
61
patched/any/any_test.patch
Normal file
@ -0,0 +1,61 @@
|
||||
Index: .
|
||||
===================================================================
|
||||
--- . (revision 86520)
|
||||
+++ . (working copy)
|
||||
@@ -91,7 +91,10 @@
|
||||
|
||||
check_true(value.empty(), "empty");
|
||||
check_null(any_cast<int>(&value), "any_cast<int>");
|
||||
+#ifndef BOOST_NO_RTTI
|
||||
check_equal(value.type(), typeid(void), "type");
|
||||
+#endif
|
||||
+ check_equal(value.type(), boost::type_id<void>(), "type boost");
|
||||
}
|
||||
|
||||
void test_converting_ctor()
|
||||
@@ -100,7 +103,10 @@
|
||||
any value = text;
|
||||
|
||||
check_false(value.empty(), "empty");
|
||||
+#ifndef BOOST_NO_RTTI
|
||||
check_equal(value.type(), typeid(std::string), "type");
|
||||
+#endif
|
||||
+ check_equal(value.type(), boost::type_id<std::string>(), "type boost");
|
||||
check_null(any_cast<int>(&value), "any_cast<int>");
|
||||
check_non_null(any_cast<std::string>(&value), "any_cast<std::string>");
|
||||
check_equal(
|
||||
@@ -158,7 +164,10 @@
|
||||
any * assign_result = &(value = text);
|
||||
|
||||
check_false(value.empty(), "type");
|
||||
+#ifndef BOOST_NO_RTTI
|
||||
check_equal(value.type(), typeid(std::string), "type");
|
||||
+#endif
|
||||
+ check_equal(value.type(), boost::type_id<std::string>(), "type boost");
|
||||
check_null(any_cast<int>(&value), "any_cast<int>");
|
||||
check_non_null(any_cast<std::string>(&value), "any_cast<std::string>");
|
||||
check_equal(
|
||||
@@ -191,7 +200,10 @@
|
||||
|
||||
check_true(original.empty(), "empty on original");
|
||||
check_false(swapped.empty(), "empty on swapped");
|
||||
+#ifndef BOOST_NO_RTTI
|
||||
check_equal(swapped.type(), typeid(std::string), "type");
|
||||
+#endif
|
||||
+ check_equal(swapped.type(), boost::type_id<std::string>(), "type boost");
|
||||
check_equal(
|
||||
text, any_cast<std::string>(swapped),
|
||||
"comparing swapped copy against original text");
|
||||
@@ -264,8 +276,12 @@
|
||||
check_false(value1.empty(), "type");
|
||||
check_false(value2.empty(), "type");
|
||||
|
||||
+#ifndef BOOST_NO_RTTI
|
||||
check_equal(value1.type(), typeid(const char*), "type");
|
||||
check_equal(value2.type(), typeid(const char*), "type");
|
||||
+#endif
|
||||
+ check_equal(value1.type(), boost::type_id<const char*>(), "type boost");
|
||||
+ check_equal(value2.type(), boost::type_id<const char*>(), "type boost");
|
||||
|
||||
check_non_null(any_cast<const char*>(&value1), "any_cast<const char*>");
|
||||
check_non_null(any_cast<const char*>(&value2), "any_cast<const char*>");
|
@ -1,135 +0,0 @@
|
||||
#ifndef BOOST_DETAIL_SP_TYPEINFO_HPP_INCLUDED
|
||||
#define BOOST_DETAIL_SP_TYPEINFO_HPP_INCLUDED
|
||||
|
||||
// MS compatible compilers support #pragma once
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
// detail/sp_typeinfo.hpp
|
||||
//
|
||||
// Copyright 2007 Peter Dimov
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#if defined( BOOST_NO_TYPEID )
|
||||
|
||||
#include <boost/current_function.hpp>
|
||||
#include <functional>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
class sp_typeinfo
|
||||
{
|
||||
private:
|
||||
|
||||
sp_typeinfo( sp_typeinfo const& );
|
||||
sp_typeinfo& operator=( sp_typeinfo const& );
|
||||
|
||||
char const * name_;
|
||||
|
||||
public:
|
||||
|
||||
explicit sp_typeinfo( char const * name ): name_( name )
|
||||
{
|
||||
}
|
||||
|
||||
bool operator==( sp_typeinfo const& rhs ) const
|
||||
{
|
||||
return this == &rhs;
|
||||
}
|
||||
|
||||
bool operator!=( sp_typeinfo const& rhs ) const
|
||||
{
|
||||
return this != &rhs;
|
||||
}
|
||||
|
||||
bool before( sp_typeinfo const& rhs ) const
|
||||
{
|
||||
return std::less< sp_typeinfo const* >()( this, &rhs );
|
||||
}
|
||||
|
||||
char const* name() const
|
||||
{
|
||||
return name_;
|
||||
}
|
||||
};
|
||||
|
||||
template<class T> struct sp_typeid_
|
||||
{
|
||||
static sp_typeinfo ti_;
|
||||
|
||||
static char const * name()
|
||||
{
|
||||
return BOOST_CURRENT_FUNCTION;
|
||||
}
|
||||
};
|
||||
|
||||
#if defined(__SUNPRO_CC)
|
||||
// see #4199, the Sun Studio compiler gets confused about static initialization
|
||||
// constructor arguments. But an assignment works just fine.
|
||||
template<class T> sp_typeinfo sp_typeid_< T >::ti_ = sp_typeid_< T >::name();
|
||||
#else
|
||||
template<class T> sp_typeinfo sp_typeid_< T >::ti_(sp_typeid_< T >::name());
|
||||
#endif
|
||||
|
||||
template<class T> struct sp_typeid_< T & >: sp_typeid_< T >
|
||||
{
|
||||
};
|
||||
|
||||
template<class T> struct sp_typeid_< T const >: sp_typeid_< T >
|
||||
{
|
||||
};
|
||||
|
||||
template<class T> struct sp_typeid_< T volatile >: sp_typeid_< T >
|
||||
{
|
||||
};
|
||||
|
||||
template<class T> struct sp_typeid_< T const volatile >: sp_typeid_< T >
|
||||
{
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#define BOOST_SP_TYPEID(T) (boost::detail::sp_typeid_<T>::ti_)
|
||||
|
||||
#else
|
||||
|
||||
#include <typeinfo>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
#if defined( BOOST_NO_STD_TYPEINFO )
|
||||
|
||||
typedef ::type_info sp_typeinfo;
|
||||
|
||||
#else
|
||||
|
||||
typedef std::type_info sp_typeinfo;
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#define BOOST_SP_TYPEID(T) typeid(T)
|
||||
|
||||
#endif
|
||||
|
||||
#endif // #ifndef BOOST_DETAIL_SP_TYPEINFO_HPP_INCLUDED
|
23
patched/graph/Jamfile.patch
Normal file
23
patched/graph/Jamfile.patch
Normal file
@ -0,0 +1,23 @@
|
||||
Index: .
|
||||
===================================================================
|
||||
--- . (revision 86520)
|
||||
+++ . (working copy)
|
||||
@@ -59,6 +59,10 @@
|
||||
/boost/test//boost_test_exec_monitor/<link>static
|
||||
../build//boost_graph
|
||||
../../regex/build//boost_regex : --log_level=all ]
|
||||
+ [ run graphviz_test.cpp
|
||||
+ /boost/test//boost_test_exec_monitor/<link>static
|
||||
+ ../build//boost_graph
|
||||
+ ../../regex/build//boost_regex : --log_level=all : : <rtti>off : testing_graphviz_no_rtti ]
|
||||
[ run metis_test.cpp : $(METIS_INPUT_FILE) ]
|
||||
[ run gursoy_atun_layout_test.cpp ]
|
||||
[ run layout_test.cpp : : : <test-info>always_show_run_output <toolset>intel:<debug-symbols>off ]
|
||||
@@ -124,6 +128,7 @@
|
||||
[ run two_graphs_common_spanning_trees_test.cpp ]
|
||||
[ run random_spanning_tree_test.cpp ../build//boost_graph ]
|
||||
[ run graphml_test.cpp ../build//boost_graph : : "graphml_test.xml" ]
|
||||
+ [ run graphml_test.cpp ../build//boost_graph : : "graphml_test.xml" : <rtti>off : testing_graphml_no_rtti ]
|
||||
[ run mas_test.cpp ../../test/build//boost_unit_test_framework/<link>static : $(TEST_DIR) ]
|
||||
[ run stoer_wagner_test.cpp ../../test/build//boost_unit_test_framework/<link>static : $(TEST_DIR) ]
|
||||
[ compile filtered_graph_properties_dijkstra.cpp ]
|
@ -1,352 +0,0 @@
|
||||
// Copyright (C) 2006 Tiago de Paula Peixoto <tiago@forked.de>
|
||||
// Copyright (C) 2004 The Trustees of Indiana University.
|
||||
//
|
||||
// Use, modification and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// Authors: Douglas Gregor
|
||||
// Andrew Lumsdaine
|
||||
// Tiago de Paula Peixoto
|
||||
|
||||
#ifndef BOOST_GRAPH_GRAPHML_HPP
|
||||
#define BOOST_GRAPH_GRAPHML_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/any.hpp>
|
||||
#include <boost/type_traits/is_convertible.hpp>
|
||||
#include <boost/graph/dll_import_export.hpp>
|
||||
#include <boost/graph/graphviz.hpp> // for exceptions
|
||||
#include <boost/type_index.hpp>
|
||||
#include <boost/mpl/bool.hpp>
|
||||
#include <boost/mpl/vector.hpp>
|
||||
#include <boost/mpl/find.hpp>
|
||||
#include <boost/mpl/for_each.hpp>
|
||||
#include <boost/property_tree/detail/xml_parser_utils.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <exception>
|
||||
#include <sstream>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Graph reader exceptions
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
struct parse_error: public graph_exception
|
||||
{
|
||||
parse_error(const std::string& err) {error = err; statement = "parse error: " + error;}
|
||||
virtual ~parse_error() throw() {}
|
||||
virtual const char* what() const throw() {return statement.c_str();}
|
||||
std::string statement;
|
||||
std::string error;
|
||||
};
|
||||
|
||||
|
||||
class mutate_graph
|
||||
{
|
||||
public:
|
||||
virtual ~mutate_graph() {}
|
||||
virtual bool is_directed() const = 0;
|
||||
|
||||
virtual boost::any do_add_vertex() = 0;
|
||||
virtual std::pair<boost::any,bool> do_add_edge(boost::any source, boost::any target) = 0;
|
||||
|
||||
virtual void
|
||||
set_graph_property(const std::string& name, const std::string& value, const std::string& value_type) = 0;
|
||||
|
||||
virtual void
|
||||
set_vertex_property(const std::string& name, boost::any vertex, const std::string& value, const std::string& value_type) = 0;
|
||||
|
||||
virtual void
|
||||
set_edge_property(const std::string& name, boost::any edge, const std::string& value, const std::string& value_type) = 0;
|
||||
};
|
||||
|
||||
template<typename MutableGraph>
|
||||
class mutate_graph_impl : public mutate_graph
|
||||
{
|
||||
typedef typename graph_traits<MutableGraph>::vertex_descriptor vertex_descriptor;
|
||||
typedef typename graph_traits<MutableGraph>::edge_descriptor edge_descriptor;
|
||||
|
||||
public:
|
||||
mutate_graph_impl(MutableGraph& g, dynamic_properties& dp)
|
||||
: m_g(g), m_dp(dp) { }
|
||||
|
||||
bool is_directed() const
|
||||
{
|
||||
return is_convertible<typename graph_traits<MutableGraph>::directed_category,
|
||||
directed_tag>::value;
|
||||
}
|
||||
|
||||
virtual any do_add_vertex()
|
||||
{
|
||||
return any(add_vertex(m_g));
|
||||
}
|
||||
|
||||
virtual std::pair<any,bool> do_add_edge(any source, any target)
|
||||
{
|
||||
std::pair<edge_descriptor,bool> retval = add_edge(any_cast<vertex_descriptor>(source),
|
||||
any_cast<vertex_descriptor>(target), m_g);
|
||||
return std::make_pair(any(retval.first), retval.second);
|
||||
}
|
||||
|
||||
virtual void
|
||||
set_graph_property(const std::string& name, const std::string& value, const std::string& value_type)
|
||||
{
|
||||
bool type_found = false;
|
||||
try
|
||||
{
|
||||
mpl::for_each<value_types>(put_property<MutableGraph,value_types>
|
||||
(name, m_dp, m_g, value, value_type, m_type_names, type_found));
|
||||
}
|
||||
catch (bad_lexical_cast)
|
||||
{
|
||||
BOOST_THROW_EXCEPTION(
|
||||
parse_error("invalid value \"" + value + "\" for key " +
|
||||
name + " of type " + value_type));
|
||||
}
|
||||
if (!type_found)
|
||||
{
|
||||
BOOST_THROW_EXCEPTION(
|
||||
parse_error("unrecognized type \"" + value_type +
|
||||
"\" for key " + name));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
virtual void
|
||||
set_vertex_property(const std::string& name, any vertex, const std::string& value, const std::string& value_type)
|
||||
{
|
||||
bool type_found = false;
|
||||
try
|
||||
{
|
||||
mpl::for_each<value_types>(put_property<vertex_descriptor,value_types>
|
||||
(name, m_dp, any_cast<vertex_descriptor>(vertex),
|
||||
value, value_type, m_type_names, type_found));
|
||||
}
|
||||
catch (bad_lexical_cast)
|
||||
{
|
||||
BOOST_THROW_EXCEPTION(
|
||||
parse_error("invalid value \"" + value + "\" for key " +
|
||||
name + " of type " + value_type));
|
||||
}
|
||||
if (!type_found)
|
||||
{
|
||||
BOOST_THROW_EXCEPTION(
|
||||
parse_error("unrecognized type \"" + value_type +
|
||||
"\" for key " + name));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
virtual void
|
||||
set_edge_property(const std::string& name, any edge, const std::string& value, const std::string& value_type)
|
||||
{
|
||||
bool type_found = false;
|
||||
try
|
||||
{
|
||||
mpl::for_each<value_types>(put_property<edge_descriptor,value_types>
|
||||
(name, m_dp, any_cast<edge_descriptor>(edge),
|
||||
value, value_type, m_type_names, type_found));
|
||||
}
|
||||
catch (bad_lexical_cast)
|
||||
{
|
||||
BOOST_THROW_EXCEPTION(
|
||||
parse_error("invalid value \"" + value + "\" for key " +
|
||||
name + " of type " + value_type));
|
||||
}
|
||||
if (!type_found)
|
||||
{
|
||||
BOOST_THROW_EXCEPTION(
|
||||
parse_error("unrecognized type \"" + value_type +
|
||||
"\" for key " + name));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Key, typename ValueVector>
|
||||
class put_property
|
||||
{
|
||||
public:
|
||||
put_property(const std::string& name, dynamic_properties& dp, const Key& key,
|
||||
const std::string& value, const std::string& value_type,
|
||||
const char** type_names, bool& type_found)
|
||||
: m_name(name), m_dp(dp), m_key(key), m_value(value),
|
||||
m_value_type(value_type), m_type_names(type_names),
|
||||
m_type_found(type_found) {}
|
||||
template <class Value>
|
||||
void operator()(Value)
|
||||
{
|
||||
if (m_value_type == m_type_names[mpl::find<ValueVector,Value>::type::pos::value])
|
||||
{
|
||||
put(m_name, m_dp, m_key, lexical_cast<Value>(m_value));
|
||||
m_type_found = true;
|
||||
}
|
||||
}
|
||||
private:
|
||||
const std::string& m_name;
|
||||
dynamic_properties& m_dp;
|
||||
const Key& m_key;
|
||||
const std::string& m_value;
|
||||
const std::string& m_value_type;
|
||||
const char** m_type_names;
|
||||
bool& m_type_found;
|
||||
};
|
||||
|
||||
protected:
|
||||
MutableGraph& m_g;
|
||||
dynamic_properties& m_dp;
|
||||
typedef mpl::vector<bool, int, long, float, double, std::string> value_types;
|
||||
static const char* m_type_names[];
|
||||
};
|
||||
|
||||
template<typename MutableGraph>
|
||||
const char* mutate_graph_impl<MutableGraph>::m_type_names[] = {"boolean", "int", "long", "float", "double", "string"};
|
||||
|
||||
void BOOST_GRAPH_DECL
|
||||
read_graphml(std::istream& in, mutate_graph& g);
|
||||
|
||||
template<typename MutableGraph>
|
||||
void
|
||||
read_graphml(std::istream& in, MutableGraph& g, dynamic_properties& dp)
|
||||
{
|
||||
mutate_graph_impl<MutableGraph> mg(g,dp);
|
||||
read_graphml(in, mg);
|
||||
}
|
||||
|
||||
template <typename Types>
|
||||
class get_type_name
|
||||
{
|
||||
public:
|
||||
get_type_name(const type_index& type, const char** type_names, std::string& type_name)
|
||||
: m_type(type), m_type_names(type_names), m_type_name(type_name) {}
|
||||
template <typename Type>
|
||||
void operator()(Type)
|
||||
{
|
||||
if (type_id<Type>() == m_type)
|
||||
m_type_name = m_type_names[mpl::find<Types,Type>::type::pos::value];
|
||||
}
|
||||
private:
|
||||
const type_index m_type;
|
||||
const char** m_type_names;
|
||||
std::string &m_type_name;
|
||||
};
|
||||
|
||||
|
||||
template <typename Graph, typename VertexIndexMap>
|
||||
void
|
||||
write_graphml(std::ostream& out, const Graph& g, VertexIndexMap vertex_index,
|
||||
const dynamic_properties& dp, bool ordered_vertices=false)
|
||||
{
|
||||
typedef typename graph_traits<Graph>::directed_category directed_category;
|
||||
typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
|
||||
|
||||
using boost::property_tree::xml_parser::encode_char_entities;
|
||||
|
||||
BOOST_STATIC_CONSTANT(bool,
|
||||
graph_is_directed =
|
||||
(is_convertible<directed_category*, directed_tag*>::value));
|
||||
|
||||
out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
||||
<< "<graphml xmlns=\"http://graphml.graphdrawing.org/xmlns\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd\">\n";
|
||||
|
||||
typedef mpl::vector<bool, short, unsigned short, int, unsigned int, long, unsigned long, long long, unsigned long long, float, double, long double, std::string> value_types;
|
||||
const char* type_names[] = {"boolean", "int", "int", "int", "int", "long", "long", "long", "long", "float", "double", "double", "string"};
|
||||
std::map<std::string, std::string> graph_key_ids;
|
||||
std::map<std::string, std::string> vertex_key_ids;
|
||||
std::map<std::string, std::string> edge_key_ids;
|
||||
int key_count = 0;
|
||||
|
||||
// Output keys
|
||||
for (dynamic_properties::const_iterator i = dp.begin(); i != dp.end(); ++i)
|
||||
{
|
||||
std::string key_id = "key" + lexical_cast<std::string>(key_count++);
|
||||
if (i->second->key() == type_id<Graph*>())
|
||||
graph_key_ids[i->first] = key_id;
|
||||
else if (i->second->key() == type_id<vertex_descriptor>())
|
||||
vertex_key_ids[i->first] = key_id;
|
||||
else if (i->second->key() == type_id<edge_descriptor>())
|
||||
edge_key_ids[i->first] = key_id;
|
||||
else
|
||||
continue;
|
||||
std::string type_name = "string";
|
||||
mpl::for_each<value_types>(get_type_name<value_types>(i->second->value(), type_names, type_name));
|
||||
out << " <key id=\"" << encode_char_entities(key_id) << "\" for=\""
|
||||
<< (i->second->key() == type_id<Graph*>() ? "graph" : (i->second->key() == type_id<vertex_descriptor>() ? "node" : "edge")) << "\""
|
||||
<< " attr.name=\"" << i->first << "\""
|
||||
<< " attr.type=\"" << type_name << "\""
|
||||
<< " />\n";
|
||||
}
|
||||
|
||||
out << " <graph id=\"G\" edgedefault=\""
|
||||
<< (graph_is_directed ? "directed" : "undirected") << "\""
|
||||
<< " parse.nodeids=\"" << (ordered_vertices ? "canonical" : "free") << "\""
|
||||
<< " parse.edgeids=\"canonical\" parse.order=\"nodesfirst\">\n";
|
||||
|
||||
// Output graph data
|
||||
for (dynamic_properties::const_iterator i = dp.begin(); i != dp.end(); ++i)
|
||||
{
|
||||
if (i->second->key() == type_id<Graph*>())
|
||||
{
|
||||
// The const_cast here is just to get typeid correct for property
|
||||
// map key; the graph should not be mutated using it.
|
||||
out << " <data key=\"" << graph_key_ids[i->first] << "\">"
|
||||
<< encode_char_entities(i->second->get_string(const_cast<Graph*>(&g))) << "</data>\n";
|
||||
}
|
||||
}
|
||||
|
||||
typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator;
|
||||
vertex_iterator v, v_end;
|
||||
for (boost::tie(v, v_end) = vertices(g); v != v_end; ++v)
|
||||
{
|
||||
out << " <node id=\"n" << get(vertex_index, *v) << "\">\n";
|
||||
// Output data
|
||||
for (dynamic_properties::const_iterator i = dp.begin(); i != dp.end(); ++i)
|
||||
{
|
||||
if (i->second->key() == type_id<vertex_descriptor>())
|
||||
{
|
||||
out << " <data key=\"" << vertex_key_ids[i->first] << "\">"
|
||||
<< encode_char_entities(i->second->get_string(*v)) << "</data>\n";
|
||||
}
|
||||
}
|
||||
out << " </node>\n";
|
||||
}
|
||||
|
||||
typedef typename graph_traits<Graph>::edge_iterator edge_iterator;
|
||||
edge_iterator e, e_end;
|
||||
typename graph_traits<Graph>::edges_size_type edge_count = 0;
|
||||
for (boost::tie(e, e_end) = edges(g); e != e_end; ++e)
|
||||
{
|
||||
out << " <edge id=\"e" << edge_count++ << "\" source=\"n"
|
||||
<< get(vertex_index, source(*e, g)) << "\" target=\"n"
|
||||
<< get(vertex_index, target(*e, g)) << "\">\n";
|
||||
|
||||
// Output data
|
||||
for (dynamic_properties::const_iterator i = dp.begin(); i != dp.end(); ++i)
|
||||
{
|
||||
if (i->second->key() == type_id<edge_descriptor>())
|
||||
{
|
||||
out << " <data key=\"" << edge_key_ids[i->first] << "\">"
|
||||
<< encode_char_entities(i->second->get_string(*e)) << "</data>\n";
|
||||
}
|
||||
}
|
||||
out << " </edge>\n";
|
||||
}
|
||||
|
||||
out << " </graph>\n"
|
||||
<< "</graphml>\n";
|
||||
}
|
||||
|
||||
|
||||
template <typename Graph>
|
||||
void
|
||||
write_graphml(std::ostream& out, const Graph& g, const dynamic_properties& dp,
|
||||
bool ordered_vertices=false)
|
||||
{
|
||||
write_graphml(out, g, get(vertex_index, g), dp, ordered_vertices);
|
||||
}
|
||||
|
||||
} // boost namespace
|
||||
|
||||
#endif // BOOST_GRAPH_GRAPHML_HPP
|
83
patched/graph/graphml.patch
Normal file
83
patched/graph/graphml.patch
Normal file
@ -0,0 +1,83 @@
|
||||
Index: .
|
||||
===================================================================
|
||||
--- . (revision 86520)
|
||||
+++ . (working copy)
|
||||
@@ -18,7 +18,7 @@
|
||||
#include <boost/type_traits/is_convertible.hpp>
|
||||
#include <boost/graph/dll_import_export.hpp>
|
||||
#include <boost/graph/graphviz.hpp> // for exceptions
|
||||
-#include <typeinfo>
|
||||
+#include <boost/type_index/type_info.hpp>
|
||||
#include <boost/mpl/bool.hpp>
|
||||
#include <boost/mpl/vector.hpp>
|
||||
#include <boost/mpl/find.hpp>
|
||||
@@ -218,16 +218,16 @@
|
||||
class get_type_name
|
||||
{
|
||||
public:
|
||||
- get_type_name(const std::type_info& type, const char** type_names, std::string& type_name)
|
||||
+ get_type_name(const boost::type_info& type, const char** type_names, std::string& type_name)
|
||||
: m_type(type), m_type_names(type_names), m_type_name(type_name) {}
|
||||
template <typename Type>
|
||||
void operator()(Type)
|
||||
{
|
||||
- if (typeid(Type) == m_type)
|
||||
+ if (boost::type_id<Type>() == m_type)
|
||||
m_type_name = m_type_names[mpl::find<Types,Type>::type::pos::value];
|
||||
}
|
||||
private:
|
||||
- const std::type_info &m_type;
|
||||
+ const boost::type_info &m_type;
|
||||
const char** m_type_names;
|
||||
std::string &m_type_name;
|
||||
};
|
||||
@@ -262,18 +262,18 @@
|
||||
for (dynamic_properties::const_iterator i = dp.begin(); i != dp.end(); ++i)
|
||||
{
|
||||
std::string key_id = "key" + lexical_cast<std::string>(key_count++);
|
||||
- if (i->second->key() == typeid(Graph*))
|
||||
+ if (i->second->key() == boost::type_id<Graph*>())
|
||||
graph_key_ids[i->first] = key_id;
|
||||
- else if (i->second->key() == typeid(vertex_descriptor))
|
||||
+ else if (i->second->key() == boost::type_id<vertex_descriptor>())
|
||||
vertex_key_ids[i->first] = key_id;
|
||||
- else if (i->second->key() == typeid(edge_descriptor))
|
||||
+ else if (i->second->key() == boost::type_id<edge_descriptor>())
|
||||
edge_key_ids[i->first] = key_id;
|
||||
else
|
||||
continue;
|
||||
std::string type_name = "string";
|
||||
mpl::for_each<value_types>(get_type_name<value_types>(i->second->value(), type_names, type_name));
|
||||
out << " <key id=\"" << encode_char_entities(key_id) << "\" for=\""
|
||||
- << (i->second->key() == typeid(Graph*) ? "graph" : (i->second->key() == typeid(vertex_descriptor) ? "node" : "edge")) << "\""
|
||||
+ << (i->second->key() == boost::type_id<Graph*>() ? "graph" : (i->second->key() == boost::type_id<vertex_descriptor>() ? "node" : "edge")) << "\""
|
||||
<< " attr.name=\"" << i->first << "\""
|
||||
<< " attr.type=\"" << type_name << "\""
|
||||
<< " />\n";
|
||||
@@ -287,7 +287,7 @@
|
||||
// Output graph data
|
||||
for (dynamic_properties::const_iterator i = dp.begin(); i != dp.end(); ++i)
|
||||
{
|
||||
- if (i->second->key() == typeid(Graph*))
|
||||
+ if (i->second->key() == boost::type_id<Graph*>())
|
||||
{
|
||||
// The const_cast here is just to get typeid correct for property
|
||||
// map key; the graph should not be mutated using it.
|
||||
@@ -304,7 +304,7 @@
|
||||
// Output data
|
||||
for (dynamic_properties::const_iterator i = dp.begin(); i != dp.end(); ++i)
|
||||
{
|
||||
- if (i->second->key() == typeid(vertex_descriptor))
|
||||
+ if (i->second->key() == boost::type_id<vertex_descriptor>())
|
||||
{
|
||||
out << " <data key=\"" << vertex_key_ids[i->first] << "\">"
|
||||
<< encode_char_entities(i->second->get_string(*v)) << "</data>\n";
|
||||
@@ -325,7 +325,7 @@
|
||||
// Output data
|
||||
for (dynamic_properties::const_iterator i = dp.begin(); i != dp.end(); ++i)
|
||||
{
|
||||
- if (i->second->key() == typeid(edge_descriptor))
|
||||
+ if (i->second->key() == boost::type_id<edge_descriptor>())
|
||||
{
|
||||
out << " <data key=\"" << edge_key_ids[i->first] << "\">"
|
||||
<< encode_char_entities(i->second->get_string(*e)) << "</data>\n";
|
30
patched/graph/graphvis.patch
Normal file
30
patched/graph/graphvis.patch
Normal file
@ -0,0 +1,30 @@
|
||||
Index: .
|
||||
===================================================================
|
||||
--- . (revision 86520)
|
||||
+++ . (working copy)
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <stdio.h> // for FILE
|
||||
+#include <boost/type_index/type_info.hpp>
|
||||
#include <boost/property_map/property_map.hpp>
|
||||
#include <boost/tuple/tuple.hpp>
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
@@ -489,7 +490,7 @@
|
||||
bool first = true;
|
||||
for (dynamic_properties::const_iterator i = dp->begin();
|
||||
i != dp->end(); ++i) {
|
||||
- if (typeid(key) == i->second->key()) {
|
||||
+ if (boost::type_id<Descriptor>() == i->second->key()) {
|
||||
if (first) out << " [";
|
||||
else out << ", ";
|
||||
first = false;
|
||||
@@ -518,7 +519,7 @@
|
||||
bool first = true;
|
||||
for (dynamic_properties::const_iterator i = dp->begin();
|
||||
i != dp->end(); ++i) {
|
||||
- if (typeid(key) == i->second->key()
|
||||
+ if (boost::type_id<Descriptor>() == i->second->key()
|
||||
&& i->first != *node_id) {
|
||||
if (first) out << " [";
|
||||
else out << ", ";
|
@ -1,858 +0,0 @@
|
||||
//=======================================================================
|
||||
// Copyright 2001 University of Notre Dame.
|
||||
// Copyright 2003 Jeremy Siek
|
||||
// Authors: Lie-Quan Lee, Jeremy Siek, and Douglas Gregor
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//=======================================================================
|
||||
#ifndef BOOST_GRAPHVIZ_HPP
|
||||
#define BOOST_GRAPHVIZ_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <stdio.h> // for FILE
|
||||
#include <boost/property_map/property_map.hpp>
|
||||
#include <boost/tuple/tuple.hpp>
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
#include <boost/graph/properties.hpp>
|
||||
#include <boost/graph/subgraph.hpp>
|
||||
#include <boost/graph/adjacency_list.hpp>
|
||||
#include <boost/property_map/dynamic_property_map.hpp>
|
||||
#include <boost/graph/overloading.hpp>
|
||||
#include <boost/graph/dll_import_export.hpp>
|
||||
#include <boost/spirit/include/classic_multi_pass.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/algorithm/string/replace.hpp>
|
||||
#include <boost/xpressive/xpressive_static.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/type_index.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
template <typename directed_category>
|
||||
struct graphviz_io_traits {
|
||||
static std::string name() {
|
||||
return "digraph";
|
||||
}
|
||||
static std::string delimiter() {
|
||||
return "->";
|
||||
} };
|
||||
|
||||
template <>
|
||||
struct graphviz_io_traits <undirected_tag> {
|
||||
static std::string name() {
|
||||
return "graph";
|
||||
}
|
||||
static std::string delimiter() {
|
||||
return "--";
|
||||
}
|
||||
};
|
||||
|
||||
struct default_writer {
|
||||
void operator()(std::ostream&) const {
|
||||
}
|
||||
template <class VorE>
|
||||
void operator()(std::ostream&, const VorE&) const {
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
inline std::string escape_dot_string(const T& obj) {
|
||||
using namespace boost::xpressive;
|
||||
static sregex valid_unquoted_id = (((alpha | '_') >> *_w) | (!as_xpr('-') >> (('.' >> *_d) | (+_d >> !('.' >> *_d)))));
|
||||
std::string s(boost::lexical_cast<std::string>(obj));
|
||||
if (regex_match(s, valid_unquoted_id)) {
|
||||
return s;
|
||||
} else {
|
||||
boost::algorithm::replace_all(s, "\"", "\\\"");
|
||||
return "\"" + s + "\"";
|
||||
}
|
||||
}
|
||||
|
||||
template <class Name>
|
||||
class label_writer {
|
||||
public:
|
||||
label_writer(Name _name) : name(_name) {}
|
||||
template <class VertexOrEdge>
|
||||
void operator()(std::ostream& out, const VertexOrEdge& v) const {
|
||||
out << "[label=" << escape_dot_string(get(name, v)) << "]";
|
||||
}
|
||||
private:
|
||||
Name name;
|
||||
};
|
||||
template <class Name>
|
||||
inline label_writer<Name>
|
||||
make_label_writer(Name n) {
|
||||
return label_writer<Name>(n);
|
||||
}
|
||||
|
||||
enum edge_attribute_t { edge_attribute = 1111 };
|
||||
enum vertex_attribute_t { vertex_attribute = 2222 };
|
||||
enum graph_graph_attribute_t { graph_graph_attribute = 3333 };
|
||||
enum graph_vertex_attribute_t { graph_vertex_attribute = 4444 };
|
||||
enum graph_edge_attribute_t { graph_edge_attribute = 5555 };
|
||||
|
||||
BOOST_INSTALL_PROPERTY(edge, attribute);
|
||||
BOOST_INSTALL_PROPERTY(vertex, attribute);
|
||||
BOOST_INSTALL_PROPERTY(graph, graph_attribute);
|
||||
BOOST_INSTALL_PROPERTY(graph, vertex_attribute);
|
||||
BOOST_INSTALL_PROPERTY(graph, edge_attribute);
|
||||
|
||||
|
||||
template <class Attribute>
|
||||
inline void write_attributes(const Attribute& attr, std::ostream& out) {
|
||||
typename Attribute::const_iterator i, iend;
|
||||
i = attr.begin();
|
||||
iend = attr.end();
|
||||
|
||||
while ( i != iend ) {
|
||||
out << i->first << "=" << escape_dot_string(i->second);
|
||||
++i;
|
||||
if ( i != iend )
|
||||
out << ", ";
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Attributes>
|
||||
inline void write_all_attributes(Attributes attributes,
|
||||
const std::string& name,
|
||||
std::ostream& out)
|
||||
{
|
||||
typename Attributes::const_iterator i = attributes.begin(),
|
||||
end = attributes.end();
|
||||
if (i != end) {
|
||||
out << name << " [\n";
|
||||
write_attributes(attributes, out);
|
||||
out << "];\n";
|
||||
}
|
||||
}
|
||||
|
||||
inline void write_all_attributes(detail::error_property_not_found,
|
||||
const std::string&,
|
||||
std::ostream&)
|
||||
{
|
||||
// Do nothing - no attributes exist
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename GraphGraphAttributes,
|
||||
typename GraphNodeAttributes,
|
||||
typename GraphEdgeAttributes>
|
||||
struct graph_attributes_writer
|
||||
{
|
||||
graph_attributes_writer(GraphGraphAttributes gg,
|
||||
GraphNodeAttributes gn,
|
||||
GraphEdgeAttributes ge)
|
||||
: g_attributes(gg), n_attributes(gn), e_attributes(ge) { }
|
||||
|
||||
void operator()(std::ostream& out) const {
|
||||
write_all_attributes(g_attributes, "graph", out);
|
||||
write_all_attributes(n_attributes, "node", out);
|
||||
write_all_attributes(e_attributes, "edge", out);
|
||||
}
|
||||
GraphGraphAttributes g_attributes;
|
||||
GraphNodeAttributes n_attributes;
|
||||
GraphEdgeAttributes e_attributes;
|
||||
};
|
||||
|
||||
template <typename GAttrMap, typename NAttrMap, typename EAttrMap>
|
||||
graph_attributes_writer<GAttrMap, NAttrMap, EAttrMap>
|
||||
make_graph_attributes_writer(const GAttrMap& g_attr, const NAttrMap& n_attr,
|
||||
const EAttrMap& e_attr) {
|
||||
return graph_attributes_writer<GAttrMap, NAttrMap, EAttrMap>
|
||||
(g_attr, n_attr, e_attr);
|
||||
}
|
||||
|
||||
|
||||
template <typename Graph>
|
||||
graph_attributes_writer
|
||||
<typename graph_property<Graph, graph_graph_attribute_t>::type,
|
||||
typename graph_property<Graph, graph_vertex_attribute_t>::type,
|
||||
typename graph_property<Graph, graph_edge_attribute_t>::type>
|
||||
make_graph_attributes_writer(const Graph& g)
|
||||
{
|
||||
typedef typename graph_property<Graph, graph_graph_attribute_t>::type
|
||||
GAttrMap;
|
||||
typedef typename graph_property<Graph, graph_vertex_attribute_t>::type
|
||||
NAttrMap;
|
||||
typedef typename graph_property<Graph, graph_edge_attribute_t>::type
|
||||
EAttrMap;
|
||||
GAttrMap gam = get_property(g, graph_graph_attribute);
|
||||
NAttrMap nam = get_property(g, graph_vertex_attribute);
|
||||
EAttrMap eam = get_property(g, graph_edge_attribute);
|
||||
graph_attributes_writer<GAttrMap, NAttrMap, EAttrMap> writer(gam, nam, eam);
|
||||
return writer;
|
||||
}
|
||||
|
||||
template <typename AttributeMap>
|
||||
struct attributes_writer {
|
||||
attributes_writer(AttributeMap attr)
|
||||
: attributes(attr) { }
|
||||
|
||||
template <class VorE>
|
||||
void operator()(std::ostream& out, const VorE& e) const {
|
||||
this->write_attribute(out, attributes[e]);
|
||||
}
|
||||
|
||||
private:
|
||||
template<typename AttributeSequence>
|
||||
void write_attribute(std::ostream& out,
|
||||
const AttributeSequence& seq) const
|
||||
{
|
||||
if (!seq.empty()) {
|
||||
out << "[";
|
||||
write_attributes(seq, out);
|
||||
out << "]";
|
||||
}
|
||||
}
|
||||
|
||||
void write_attribute(std::ostream&,
|
||||
detail::error_property_not_found) const
|
||||
{
|
||||
}
|
||||
AttributeMap attributes;
|
||||
};
|
||||
|
||||
template <typename Graph>
|
||||
attributes_writer
|
||||
<typename property_map<Graph, edge_attribute_t>::const_type>
|
||||
make_edge_attributes_writer(const Graph& g)
|
||||
{
|
||||
typedef typename property_map<Graph, edge_attribute_t>::const_type
|
||||
EdgeAttributeMap;
|
||||
return attributes_writer<EdgeAttributeMap>(get(edge_attribute, g));
|
||||
}
|
||||
|
||||
template <typename Graph>
|
||||
attributes_writer
|
||||
<typename property_map<Graph, vertex_attribute_t>::const_type>
|
||||
make_vertex_attributes_writer(const Graph& g)
|
||||
{
|
||||
typedef typename property_map<Graph, vertex_attribute_t>::const_type
|
||||
VertexAttributeMap;
|
||||
return attributes_writer<VertexAttributeMap>(get(vertex_attribute, g));
|
||||
}
|
||||
|
||||
template <typename Graph, typename VertexPropertiesWriter,
|
||||
typename EdgePropertiesWriter, typename GraphPropertiesWriter,
|
||||
typename VertexID>
|
||||
inline void
|
||||
write_graphviz
|
||||
(std::ostream& out, const Graph& g,
|
||||
VertexPropertiesWriter vpw,
|
||||
EdgePropertiesWriter epw,
|
||||
GraphPropertiesWriter gpw,
|
||||
VertexID vertex_id
|
||||
BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,vertex_list_graph_tag))
|
||||
{
|
||||
BOOST_CONCEPT_ASSERT((EdgeListGraphConcept<Graph>));
|
||||
|
||||
typedef typename graph_traits<Graph>::directed_category cat_type;
|
||||
typedef graphviz_io_traits<cat_type> Traits;
|
||||
std::string name = "G";
|
||||
out << Traits::name() << " " << escape_dot_string(name) << " {" << std::endl;
|
||||
|
||||
gpw(out); //print graph properties
|
||||
|
||||
typename graph_traits<Graph>::vertex_iterator i, end;
|
||||
|
||||
for(boost::tie(i,end) = vertices(g); i != end; ++i) {
|
||||
out << escape_dot_string(get(vertex_id, *i));
|
||||
vpw(out, *i); //print vertex attributes
|
||||
out << ";" << std::endl;
|
||||
}
|
||||
typename graph_traits<Graph>::edge_iterator ei, edge_end;
|
||||
for(boost::tie(ei, edge_end) = edges(g); ei != edge_end; ++ei) {
|
||||
out << escape_dot_string(get(vertex_id, source(*ei, g))) << Traits::delimiter() << escape_dot_string(get(vertex_id, target(*ei, g))) << " ";
|
||||
epw(out, *ei); //print edge attributes
|
||||
out << ";" << std::endl;
|
||||
}
|
||||
out << "}" << std::endl;
|
||||
}
|
||||
|
||||
template <typename Graph, typename VertexPropertiesWriter,
|
||||
typename EdgePropertiesWriter, typename GraphPropertiesWriter>
|
||||
inline void
|
||||
write_graphviz(std::ostream& out, const Graph& g,
|
||||
VertexPropertiesWriter vpw,
|
||||
EdgePropertiesWriter epw,
|
||||
GraphPropertiesWriter gpw
|
||||
BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,vertex_list_graph_tag))
|
||||
{ write_graphviz(out, g, vpw, epw, gpw, get(vertex_index, g)); }
|
||||
|
||||
#if !defined(BOOST_MSVC) || BOOST_MSVC > 1300
|
||||
// ambiguous overload problem with VC++
|
||||
template <typename Graph>
|
||||
inline void
|
||||
write_graphviz(std::ostream& out, const Graph& g
|
||||
BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,vertex_list_graph_tag))
|
||||
{
|
||||
default_writer dw;
|
||||
default_writer gw;
|
||||
write_graphviz(out, g, dw, dw, gw);
|
||||
}
|
||||
#endif
|
||||
|
||||
template <typename Graph, typename VertexWriter>
|
||||
inline void
|
||||
write_graphviz(std::ostream& out, const Graph& g, VertexWriter vw
|
||||
BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,vertex_list_graph_tag))
|
||||
{
|
||||
default_writer dw;
|
||||
default_writer gw;
|
||||
write_graphviz(out, g, vw, dw, gw);
|
||||
}
|
||||
|
||||
template <typename Graph, typename VertexWriter, typename EdgeWriter>
|
||||
inline void
|
||||
write_graphviz(std::ostream& out, const Graph& g,
|
||||
VertexWriter vw, EdgeWriter ew
|
||||
BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,vertex_list_graph_tag))
|
||||
{
|
||||
default_writer gw;
|
||||
write_graphviz(out, g, vw, ew, gw);
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <class Graph_, class RandomAccessIterator, class VertexID>
|
||||
void write_graphviz_subgraph (std::ostream& out,
|
||||
const subgraph<Graph_>& g,
|
||||
RandomAccessIterator vertex_marker,
|
||||
RandomAccessIterator edge_marker,
|
||||
VertexID vertex_id)
|
||||
{
|
||||
typedef subgraph<Graph_> Graph;
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
|
||||
typedef typename graph_traits<Graph>::directed_category cat_type;
|
||||
typedef graphviz_io_traits<cat_type> Traits;
|
||||
|
||||
typedef typename graph_property<Graph, graph_name_t>::type NameType;
|
||||
const NameType& g_name = get_property(g, graph_name);
|
||||
|
||||
if ( g.is_root() )
|
||||
out << Traits::name() ;
|
||||
else
|
||||
out << "subgraph";
|
||||
|
||||
out << " " << escape_dot_string(g_name) << " {" << std::endl;
|
||||
|
||||
typename Graph::const_children_iterator i_child, j_child;
|
||||
|
||||
//print graph/node/edge attributes
|
||||
#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300
|
||||
typedef typename graph_property<Graph, graph_graph_attribute_t>::type
|
||||
GAttrMap;
|
||||
typedef typename graph_property<Graph, graph_vertex_attribute_t>::type
|
||||
NAttrMap;
|
||||
typedef typename graph_property<Graph, graph_edge_attribute_t>::type
|
||||
EAttrMap;
|
||||
GAttrMap gam = get_property(g, graph_graph_attribute);
|
||||
NAttrMap nam = get_property(g, graph_vertex_attribute);
|
||||
EAttrMap eam = get_property(g, graph_edge_attribute);
|
||||
graph_attributes_writer<GAttrMap, NAttrMap, EAttrMap> writer(gam, nam, eam);
|
||||
writer(out);
|
||||
#else
|
||||
make_graph_attributes_writer(g)(out);
|
||||
#endif
|
||||
|
||||
//print subgraph
|
||||
for ( boost::tie(i_child,j_child) = g.children();
|
||||
i_child != j_child; ++i_child )
|
||||
write_graphviz_subgraph(out, *i_child, vertex_marker, edge_marker,
|
||||
vertex_id);
|
||||
|
||||
// Print out vertices and edges not in the subgraphs.
|
||||
|
||||
typename graph_traits<Graph>::vertex_iterator i, end;
|
||||
typename graph_traits<Graph>::edge_iterator ei, edge_end;
|
||||
|
||||
for(boost::tie(i,end) = vertices(g); i != end; ++i) {
|
||||
Vertex v = g.local_to_global(*i);
|
||||
int pos = get(vertex_id, v);
|
||||
if ( vertex_marker[pos] ) {
|
||||
vertex_marker[pos] = false;
|
||||
out << escape_dot_string(pos);
|
||||
#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300
|
||||
typedef typename property_map<Graph, vertex_attribute_t>::const_type
|
||||
VertexAttributeMap;
|
||||
attributes_writer<VertexAttributeMap> vawriter(get(vertex_attribute,
|
||||
g.root()));
|
||||
vawriter(out, v);
|
||||
#else
|
||||
make_vertex_attributes_writer(g.root())(out, v);
|
||||
#endif
|
||||
out << ";" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
for (boost::tie(ei, edge_end) = edges(g); ei != edge_end; ++ei) {
|
||||
Vertex u = g.local_to_global(source(*ei,g)),
|
||||
v = g.local_to_global(target(*ei, g));
|
||||
int pos = get(get(edge_index, g.root()), g.local_to_global(*ei));
|
||||
if ( edge_marker[pos] ) {
|
||||
edge_marker[pos] = false;
|
||||
out << escape_dot_string(get(vertex_id, u)) << " " << Traits::delimiter()
|
||||
<< " " << escape_dot_string(get(vertex_id, v));
|
||||
#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300
|
||||
typedef typename property_map<Graph, edge_attribute_t>::const_type
|
||||
EdgeAttributeMap;
|
||||
attributes_writer<EdgeAttributeMap> eawriter(get(edge_attribute, g));
|
||||
eawriter(out, *ei);
|
||||
#else
|
||||
make_edge_attributes_writer(g)(out, *ei); //print edge properties
|
||||
#endif
|
||||
out << ";" << std::endl;
|
||||
}
|
||||
}
|
||||
out << "}" << std::endl;
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
// requires graph_name graph property
|
||||
template <typename Graph>
|
||||
void write_graphviz(std::ostream& out, const subgraph<Graph>& g) {
|
||||
std::vector<bool> edge_marker(num_edges(g), true);
|
||||
std::vector<bool> vertex_marker(num_vertices(g), true);
|
||||
|
||||
detail::write_graphviz_subgraph(out, g,
|
||||
vertex_marker.begin(),
|
||||
edge_marker.begin(),
|
||||
get(vertex_index, g));
|
||||
}
|
||||
|
||||
template <typename Graph>
|
||||
void write_graphviz(const std::string& filename, const subgraph<Graph>& g) {
|
||||
std::ofstream out(filename.c_str());
|
||||
std::vector<bool> edge_marker(num_edges(g), true);
|
||||
std::vector<bool> vertex_marker(num_vertices(g), true);
|
||||
|
||||
detail::write_graphviz_subgraph(out, g,
|
||||
vertex_marker.begin(),
|
||||
edge_marker.begin(),
|
||||
get(vertex_index, g));
|
||||
}
|
||||
|
||||
template <typename Graph, typename VertexID>
|
||||
void write_graphviz(std::ostream& out, const subgraph<Graph>& g,
|
||||
VertexID vertex_id)
|
||||
{
|
||||
std::vector<bool> edge_marker(num_edges(g), true);
|
||||
std::vector<bool> vertex_marker(num_vertices(g), true);
|
||||
|
||||
detail::write_graphviz_subgraph(out, g,
|
||||
vertex_marker.begin(),
|
||||
edge_marker.begin(),
|
||||
vertex_id);
|
||||
}
|
||||
|
||||
template <typename Graph, typename VertexID>
|
||||
void write_graphviz(const std::string& filename, const subgraph<Graph>& g,
|
||||
VertexID vertex_id)
|
||||
{
|
||||
std::ofstream out(filename.c_str());
|
||||
std::vector<bool> edge_marker(num_edges(g), true);
|
||||
std::vector<bool> vertex_marker(num_vertices(g), true);
|
||||
|
||||
detail::write_graphviz_subgraph(out, g,
|
||||
vertex_marker.begin(),
|
||||
edge_marker.begin(),
|
||||
vertex_id);
|
||||
}
|
||||
|
||||
#if 0
|
||||
// This interface has not worked for a long time
|
||||
typedef std::map<std::string, std::string> GraphvizAttrList;
|
||||
|
||||
typedef property<vertex_attribute_t, GraphvizAttrList>
|
||||
GraphvizVertexProperty;
|
||||
|
||||
typedef property<edge_attribute_t, GraphvizAttrList,
|
||||
property<edge_index_t, int> >
|
||||
GraphvizEdgeProperty;
|
||||
|
||||
typedef property<graph_graph_attribute_t, GraphvizAttrList,
|
||||
property<graph_vertex_attribute_t, GraphvizAttrList,
|
||||
property<graph_edge_attribute_t, GraphvizAttrList,
|
||||
property<graph_name_t, std::string> > > >
|
||||
GraphvizGraphProperty;
|
||||
|
||||
typedef subgraph<adjacency_list<vecS,
|
||||
vecS, directedS,
|
||||
GraphvizVertexProperty,
|
||||
GraphvizEdgeProperty,
|
||||
GraphvizGraphProperty> >
|
||||
GraphvizDigraph;
|
||||
|
||||
typedef subgraph<adjacency_list<vecS,
|
||||
vecS, undirectedS,
|
||||
GraphvizVertexProperty,
|
||||
GraphvizEdgeProperty,
|
||||
GraphvizGraphProperty> >
|
||||
GraphvizGraph;
|
||||
|
||||
// These four require linking the BGL-Graphviz library: libbgl-viz.a
|
||||
// from the /src directory.
|
||||
// Library has not existed for a while
|
||||
extern void read_graphviz(const std::string& file, GraphvizDigraph& g);
|
||||
extern void read_graphviz(FILE* file, GraphvizDigraph& g);
|
||||
|
||||
extern void read_graphviz(const std::string& file, GraphvizGraph& g);
|
||||
extern void read_graphviz(FILE* file, GraphvizGraph& g);
|
||||
#endif
|
||||
|
||||
class dynamic_properties_writer
|
||||
{
|
||||
public:
|
||||
dynamic_properties_writer(const dynamic_properties& dp) : dp(&dp) { }
|
||||
|
||||
template<typename Descriptor>
|
||||
void operator()(std::ostream& out, Descriptor key) const
|
||||
{
|
||||
bool first = true;
|
||||
for (dynamic_properties::const_iterator i = dp->begin();
|
||||
i != dp->end(); ++i) {
|
||||
if (type_id<Descriptor>() == i->second->key()) {
|
||||
if (first) out << " [";
|
||||
else out << ", ";
|
||||
first = false;
|
||||
|
||||
out << i->first << "=" << escape_dot_string(i->second->get_string(key));
|
||||
}
|
||||
}
|
||||
|
||||
if (!first) out << "]";
|
||||
}
|
||||
|
||||
private:
|
||||
const dynamic_properties* dp;
|
||||
};
|
||||
|
||||
class dynamic_vertex_properties_writer
|
||||
{
|
||||
public:
|
||||
dynamic_vertex_properties_writer(const dynamic_properties& dp,
|
||||
const std::string& node_id)
|
||||
: dp(&dp), node_id(&node_id) { }
|
||||
|
||||
template<typename Descriptor>
|
||||
void operator()(std::ostream& out, Descriptor key) const
|
||||
{
|
||||
bool first = true;
|
||||
for (dynamic_properties::const_iterator i = dp->begin();
|
||||
i != dp->end(); ++i) {
|
||||
if (type_id<Descriptor>(key) == i->second->key()
|
||||
&& i->first != *node_id) {
|
||||
if (first) out << " [";
|
||||
else out << ", ";
|
||||
first = false;
|
||||
|
||||
out << i->first << "=" << escape_dot_string(i->second->get_string(key));
|
||||
}
|
||||
}
|
||||
|
||||
if (!first) out << "]";
|
||||
}
|
||||
|
||||
private:
|
||||
const dynamic_properties* dp;
|
||||
const std::string* node_id;
|
||||
};
|
||||
|
||||
namespace graph { namespace detail {
|
||||
|
||||
template<typename Vertex>
|
||||
struct node_id_property_map
|
||||
{
|
||||
typedef std::string value_type;
|
||||
typedef value_type reference;
|
||||
typedef Vertex key_type;
|
||||
typedef readable_property_map_tag category;
|
||||
|
||||
node_id_property_map() {}
|
||||
|
||||
node_id_property_map(const dynamic_properties& dp,
|
||||
const std::string& node_id)
|
||||
: dp(&dp), node_id(&node_id) { }
|
||||
|
||||
const dynamic_properties* dp;
|
||||
const std::string* node_id;
|
||||
};
|
||||
|
||||
template<typename Vertex>
|
||||
inline std::string
|
||||
get(node_id_property_map<Vertex> pm,
|
||||
typename node_id_property_map<Vertex>::key_type v)
|
||||
{ return get(*pm.node_id, *pm.dp, v); }
|
||||
|
||||
} } // end namespace graph::detail
|
||||
|
||||
template<typename Graph>
|
||||
inline void
|
||||
write_graphviz_dp(std::ostream& out, const Graph& g,
|
||||
const dynamic_properties& dp,
|
||||
const std::string& node_id = "node_id"
|
||||
BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,vertex_list_graph_tag))
|
||||
{
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
|
||||
write_graphviz_dp(out, g, dp, node_id,
|
||||
graph::detail::node_id_property_map<Vertex>(dp, node_id));
|
||||
}
|
||||
|
||||
template<typename Graph, typename VertexID>
|
||||
void
|
||||
write_graphviz_dp(std::ostream& out, const Graph& g,
|
||||
const dynamic_properties& dp, const std::string& node_id,
|
||||
VertexID id
|
||||
BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph,vertex_list_graph_tag))
|
||||
{
|
||||
write_graphviz
|
||||
(out, g,
|
||||
/*vertex_writer=*/dynamic_vertex_properties_writer(dp, node_id),
|
||||
/*edge_writer=*/dynamic_properties_writer(dp),
|
||||
/*graph_writer=*/default_writer(),
|
||||
id);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Graph reader exceptions
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
struct graph_exception : public std::exception {
|
||||
virtual ~graph_exception() throw() {}
|
||||
virtual const char* what() const throw() = 0;
|
||||
};
|
||||
|
||||
struct bad_parallel_edge : public graph_exception {
|
||||
std::string from;
|
||||
std::string to;
|
||||
mutable std::string statement;
|
||||
bad_parallel_edge(const std::string& i, const std::string& j) :
|
||||
from(i), to(j) {}
|
||||
|
||||
virtual ~bad_parallel_edge() throw() {}
|
||||
const char* what() const throw() {
|
||||
if(statement.empty())
|
||||
statement =
|
||||
std::string("Failed to add parallel edge: (")
|
||||
+ from + "," + to + ")\n";
|
||||
|
||||
return statement.c_str();
|
||||
}
|
||||
};
|
||||
|
||||
struct directed_graph_error : public graph_exception {
|
||||
virtual ~directed_graph_error() throw() {}
|
||||
virtual const char* what() const throw() {
|
||||
return
|
||||
"read_graphviz: "
|
||||
"Tried to read a directed graph into an undirected graph.";
|
||||
}
|
||||
};
|
||||
|
||||
struct undirected_graph_error : public graph_exception {
|
||||
virtual ~undirected_graph_error() throw() {}
|
||||
virtual const char* what() const throw() {
|
||||
return
|
||||
"read_graphviz: "
|
||||
"Tried to read an undirected graph into a directed graph.";
|
||||
}
|
||||
};
|
||||
|
||||
struct bad_graphviz_syntax: public graph_exception {
|
||||
std::string errmsg;
|
||||
bad_graphviz_syntax(const std::string& errmsg)
|
||||
: errmsg(errmsg) {}
|
||||
const char* what() const throw () {return errmsg.c_str();}
|
||||
~bad_graphviz_syntax() throw () {};
|
||||
};
|
||||
|
||||
namespace detail { namespace graph {
|
||||
|
||||
typedef std::string id_t;
|
||||
typedef id_t node_t;
|
||||
|
||||
// edges are not uniquely determined by adjacent nodes
|
||||
class edge_t {
|
||||
int idx_;
|
||||
explicit edge_t(int i) : idx_(i) {}
|
||||
public:
|
||||
static edge_t new_edge() {
|
||||
static int idx = 0;
|
||||
return edge_t(idx++);
|
||||
};
|
||||
|
||||
bool operator==(const edge_t& rhs) const {
|
||||
return idx_ == rhs.idx_;
|
||||
}
|
||||
bool operator<(const edge_t& rhs) const {
|
||||
return idx_ < rhs.idx_;
|
||||
}
|
||||
};
|
||||
|
||||
class mutate_graph
|
||||
{
|
||||
public:
|
||||
virtual ~mutate_graph() {}
|
||||
virtual bool is_directed() const = 0;
|
||||
virtual void do_add_vertex(const node_t& node) = 0;
|
||||
|
||||
virtual void
|
||||
do_add_edge(const edge_t& edge, const node_t& source, const node_t& target)
|
||||
= 0;
|
||||
|
||||
virtual void
|
||||
set_node_property(const id_t& key, const node_t& node, const id_t& value) = 0;
|
||||
|
||||
virtual void
|
||||
set_edge_property(const id_t& key, const edge_t& edge, const id_t& value) = 0;
|
||||
|
||||
virtual void // RG: need new second parameter to support BGL subgraphs
|
||||
set_graph_property(const id_t& key, const id_t& value) = 0;
|
||||
};
|
||||
|
||||
template<typename MutableGraph>
|
||||
class mutate_graph_impl : public mutate_graph
|
||||
{
|
||||
typedef typename graph_traits<MutableGraph>::vertex_descriptor bgl_vertex_t;
|
||||
typedef typename graph_traits<MutableGraph>::edge_descriptor bgl_edge_t;
|
||||
|
||||
public:
|
||||
mutate_graph_impl(MutableGraph& graph, dynamic_properties& dp,
|
||||
std::string node_id_prop)
|
||||
: graph_(graph), dp_(dp), node_id_prop_(node_id_prop) { }
|
||||
|
||||
~mutate_graph_impl() {}
|
||||
|
||||
bool is_directed() const
|
||||
{
|
||||
return
|
||||
boost::is_convertible<
|
||||
typename boost::graph_traits<MutableGraph>::directed_category,
|
||||
boost::directed_tag>::value;
|
||||
}
|
||||
|
||||
virtual void do_add_vertex(const node_t& node)
|
||||
{
|
||||
// Add the node to the graph.
|
||||
bgl_vertex_t v = add_vertex(graph_);
|
||||
|
||||
// Set up a mapping from name to BGL vertex.
|
||||
bgl_nodes.insert(std::make_pair(node, v));
|
||||
|
||||
// node_id_prop_ allows the caller to see the real id names for nodes.
|
||||
put(node_id_prop_, dp_, v, node);
|
||||
}
|
||||
|
||||
void
|
||||
do_add_edge(const edge_t& edge, const node_t& source, const node_t& target)
|
||||
{
|
||||
std::pair<bgl_edge_t, bool> result =
|
||||
add_edge(bgl_nodes[source], bgl_nodes[target], graph_);
|
||||
|
||||
if(!result.second) {
|
||||
// In the case of no parallel edges allowed
|
||||
boost::throw_exception(bad_parallel_edge(source, target));
|
||||
} else {
|
||||
bgl_edges.insert(std::make_pair(edge, result.first));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
set_node_property(const id_t& key, const node_t& node, const id_t& value)
|
||||
{
|
||||
put(key, dp_, bgl_nodes[node], value);
|
||||
}
|
||||
|
||||
void
|
||||
set_edge_property(const id_t& key, const edge_t& edge, const id_t& value)
|
||||
{
|
||||
put(key, dp_, bgl_edges[edge], value);
|
||||
}
|
||||
|
||||
void
|
||||
set_graph_property(const id_t& key, const id_t& value)
|
||||
{
|
||||
/* RG: pointer to graph prevents copying */
|
||||
put(key, dp_, &graph_, value);
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
MutableGraph& graph_;
|
||||
dynamic_properties& dp_;
|
||||
std::string node_id_prop_;
|
||||
std::map<node_t, bgl_vertex_t> bgl_nodes;
|
||||
std::map<edge_t, bgl_edge_t> bgl_edges;
|
||||
};
|
||||
|
||||
} } } // end namespace boost::detail::graph
|
||||
|
||||
#ifdef BOOST_GRAPH_USE_SPIRIT_PARSER
|
||||
# ifndef BOOST_GRAPH_READ_GRAPHVIZ_ITERATORS
|
||||
# define BOOST_GRAPH_READ_GRAPHVIZ_ITERATORS
|
||||
# endif
|
||||
# include <boost/graph/detail/read_graphviz_spirit.hpp>
|
||||
#else // New default parser
|
||||
# include <boost/graph/detail/read_graphviz_new.hpp>
|
||||
#endif // BOOST_GRAPH_USE_SPIRIT_PARSER
|
||||
|
||||
namespace boost {
|
||||
|
||||
// Parse the passed string as a GraphViz dot file.
|
||||
template <typename MutableGraph>
|
||||
bool read_graphviz(const std::string& data,
|
||||
MutableGraph& graph,
|
||||
dynamic_properties& dp,
|
||||
std::string const& node_id = "node_id") {
|
||||
#ifdef BOOST_GRAPH_USE_SPIRIT_PARSER
|
||||
return read_graphviz_spirit(data.begin(), data.end(), graph, dp, node_id);
|
||||
#else // Non-Spirit parser
|
||||
return read_graphviz_new(data,graph,dp,node_id);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Parse the passed iterator range as a GraphViz dot file.
|
||||
template <typename InputIterator, typename MutableGraph>
|
||||
bool read_graphviz(InputIterator user_first,
|
||||
InputIterator user_last,
|
||||
MutableGraph& graph,
|
||||
dynamic_properties& dp,
|
||||
std::string const& node_id = "node_id") {
|
||||
#ifdef BOOST_GRAPH_USE_SPIRIT_PARSER
|
||||
typedef InputIterator is_t;
|
||||
typedef boost::spirit::classic::multi_pass<is_t> iterator_t;
|
||||
|
||||
iterator_t first(boost::spirit::classic::make_multi_pass(user_first));
|
||||
iterator_t last(boost::spirit::classic::make_multi_pass(user_last));
|
||||
|
||||
return read_graphviz_spirit(first, last, graph, dp, node_id);
|
||||
#else // Non-Spirit parser
|
||||
return read_graphviz_new(std::string(user_first, user_last), graph, dp, node_id);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Parse the passed stream as a GraphViz dot file.
|
||||
template <typename MutableGraph>
|
||||
bool read_graphviz(std::istream& in, MutableGraph& graph,
|
||||
dynamic_properties& dp,
|
||||
std::string const& node_id = "node_id")
|
||||
{
|
||||
typedef std::istream_iterator<char> is_t;
|
||||
in >> std::noskipws;
|
||||
return read_graphviz(is_t(in), is_t(), graph, dp, node_id);
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#ifdef BOOST_GRAPH_USE_MPI
|
||||
# include <boost/graph/distributed/graphviz.hpp>
|
||||
#endif
|
||||
|
||||
#endif // BOOST_GRAPHVIZ_HPP
|
@ -1,615 +0,0 @@
|
||||
// Copyright 2004 The Trustees of Indiana University.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// Authors: Douglas Gregor
|
||||
// Peter Gottschling
|
||||
// Andrew Lumsdaine
|
||||
#ifndef BOOST_PARALLEL_DISTRIBUTION_HPP
|
||||
#define BOOST_PARALLEL_DISTRIBUTION_HPP
|
||||
|
||||
#ifndef BOOST_GRAPH_USE_MPI
|
||||
#error "Parallel BGL files should not be included unless <boost/graph/use_mpi.hpp> has been included"
|
||||
#endif
|
||||
|
||||
#include <cstddef>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <numeric>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/iterator/counting_iterator.hpp>
|
||||
#include <boost/random/uniform_int.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/type_index.hpp>
|
||||
|
||||
namespace boost { namespace parallel {
|
||||
|
||||
template<typename ProcessGroup, typename SizeType = std::size_t>
|
||||
class variant_distribution
|
||||
{
|
||||
public:
|
||||
typedef typename ProcessGroup::process_id_type process_id_type;
|
||||
typedef typename ProcessGroup::process_size_type process_size_type;
|
||||
typedef SizeType size_type;
|
||||
|
||||
private:
|
||||
struct basic_distribution
|
||||
{
|
||||
virtual ~basic_distribution() {}
|
||||
virtual size_type block_size(process_id_type, size_type) const = 0;
|
||||
virtual process_id_type in_process(size_type) const = 0;
|
||||
virtual size_type local(size_type) const = 0;
|
||||
virtual size_type global(size_type) const = 0;
|
||||
virtual size_type global(process_id_type, size_type) const = 0;
|
||||
virtual void* address() = 0;
|
||||
virtual const void* address() const = 0;
|
||||
virtual type_index type() const = 0;
|
||||
};
|
||||
|
||||
template<typename Distribution>
|
||||
struct poly_distribution : public basic_distribution
|
||||
{
|
||||
explicit poly_distribution(const Distribution& distribution)
|
||||
: distribution_(distribution) { }
|
||||
|
||||
virtual size_type block_size(process_id_type id, size_type n) const
|
||||
{ return distribution_.block_size(id, n); }
|
||||
|
||||
virtual process_id_type in_process(size_type i) const
|
||||
{ return distribution_(i); }
|
||||
|
||||
virtual size_type local(size_type i) const
|
||||
{ return distribution_.local(i); }
|
||||
|
||||
virtual size_type global(size_type n) const
|
||||
{ return distribution_.global(n); }
|
||||
|
||||
virtual size_type global(process_id_type id, size_type n) const
|
||||
{ return distribution_.global(id, n); }
|
||||
|
||||
virtual void* address() { return &distribution_; }
|
||||
virtual const void* address() const { return &distribution_; }
|
||||
virtual type_index type() const { return type_id<Distribution>(); }
|
||||
|
||||
private:
|
||||
Distribution distribution_;
|
||||
};
|
||||
|
||||
public:
|
||||
variant_distribution() { }
|
||||
|
||||
template<typename Distribution>
|
||||
variant_distribution(const Distribution& distribution)
|
||||
: distribution_(new poly_distribution<Distribution>(distribution)) { }
|
||||
|
||||
size_type block_size(process_id_type id, size_type n) const
|
||||
{ return distribution_->block_size(id, n); }
|
||||
|
||||
process_id_type operator()(size_type i) const
|
||||
{ return distribution_->in_process(i); }
|
||||
|
||||
size_type local(size_type i) const
|
||||
{ return distribution_->local(i); }
|
||||
|
||||
size_type global(size_type n) const
|
||||
{ return distribution_->global(n); }
|
||||
|
||||
size_type global(process_id_type id, size_type n) const
|
||||
{ return distribution_->global(id, n); }
|
||||
|
||||
operator bool() const { return distribution_; }
|
||||
|
||||
void clear() { distribution_.reset(); }
|
||||
|
||||
template<typename T>
|
||||
T* as()
|
||||
{
|
||||
if (distribution_->type() == type_id<T>())
|
||||
return static_cast<T*>(distribution_->address());
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
const T* as() const
|
||||
{
|
||||
if (distribution_->type() == type_id<T>())
|
||||
return static_cast<T*>(distribution_->address());
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
private:
|
||||
shared_ptr<basic_distribution> distribution_;
|
||||
};
|
||||
|
||||
struct block
|
||||
{
|
||||
template<typename LinearProcessGroup>
|
||||
explicit block(const LinearProcessGroup& pg, std::size_t n)
|
||||
: id(process_id(pg)), p(num_processes(pg)), n(n) { }
|
||||
|
||||
// If there are n elements in the distributed data structure, returns the number of elements stored locally.
|
||||
template<typename SizeType>
|
||||
SizeType block_size(SizeType n) const
|
||||
{ return (n / p) + ((std::size_t)(n % p) > id? 1 : 0); }
|
||||
|
||||
// If there are n elements in the distributed data structure, returns the number of elements stored on processor ID
|
||||
template<typename SizeType, typename ProcessID>
|
||||
SizeType block_size(ProcessID id, SizeType n) const
|
||||
{ return (n / p) + ((ProcessID)(n % p) > id? 1 : 0); }
|
||||
|
||||
// Returns the processor on which element with global index i is stored
|
||||
template<typename SizeType>
|
||||
SizeType operator()(SizeType i) const
|
||||
{
|
||||
SizeType cutoff_processor = n % p;
|
||||
SizeType cutoff = cutoff_processor * (n / p + 1);
|
||||
|
||||
if (i < cutoff) return i / (n / p + 1);
|
||||
else return cutoff_processor + (i - cutoff) / (n / p);
|
||||
}
|
||||
|
||||
// Find the starting index for processor with the given id
|
||||
template<typename ID>
|
||||
std::size_t start(ID id) const
|
||||
{
|
||||
std::size_t estimate = id * (n / p + 1);
|
||||
ID cutoff_processor = n % p;
|
||||
if (id < cutoff_processor) return estimate;
|
||||
else return estimate - (id - cutoff_processor);
|
||||
}
|
||||
|
||||
// Find the local index for the ith global element
|
||||
template<typename SizeType>
|
||||
SizeType local(SizeType i) const
|
||||
{
|
||||
SizeType owner = (*this)(i);
|
||||
return i - start(owner);
|
||||
}
|
||||
|
||||
// Returns the global index of local element i
|
||||
template<typename SizeType>
|
||||
SizeType global(SizeType i) const
|
||||
{ return global(id, i); }
|
||||
|
||||
// Returns the global index of the ith local element on processor id
|
||||
template<typename ProcessID, typename SizeType>
|
||||
SizeType global(ProcessID id, SizeType i) const
|
||||
{ return i + start(id); }
|
||||
|
||||
private:
|
||||
std::size_t id; //< The ID number of this processor
|
||||
std::size_t p; //< The number of processors
|
||||
std::size_t n; //< The size of the problem space
|
||||
};
|
||||
|
||||
// Block distribution with arbitrary block sizes
|
||||
struct uneven_block
|
||||
{
|
||||
typedef std::vector<std::size_t> size_vector;
|
||||
|
||||
template<typename LinearProcessGroup>
|
||||
explicit uneven_block(const LinearProcessGroup& pg, const std::vector<std::size_t>& local_sizes)
|
||||
: id(process_id(pg)), p(num_processes(pg)), local_sizes(local_sizes)
|
||||
{
|
||||
BOOST_ASSERT(local_sizes.size() == p);
|
||||
local_starts.resize(p + 1);
|
||||
local_starts[0] = 0;
|
||||
std::partial_sum(local_sizes.begin(), local_sizes.end(), &local_starts[1]);
|
||||
n = local_starts[p];
|
||||
}
|
||||
|
||||
// To do maybe: enter local size in each process and gather in constructor (much handier)
|
||||
// template<typename LinearProcessGroup>
|
||||
// explicit uneven_block(const LinearProcessGroup& pg, std::size_t my_local_size)
|
||||
|
||||
// If there are n elements in the distributed data structure, returns the number of elements stored locally.
|
||||
template<typename SizeType>
|
||||
SizeType block_size(SizeType) const
|
||||
{ return local_sizes[id]; }
|
||||
|
||||
// If there are n elements in the distributed data structure, returns the number of elements stored on processor ID
|
||||
template<typename SizeType, typename ProcessID>
|
||||
SizeType block_size(ProcessID id, SizeType) const
|
||||
{ return local_sizes[id]; }
|
||||
|
||||
// Returns the processor on which element with global index i is stored
|
||||
template<typename SizeType>
|
||||
SizeType operator()(SizeType i) const
|
||||
{
|
||||
BOOST_ASSERT (i >= (SizeType) 0 && i < (SizeType) n); // check for valid range
|
||||
size_vector::const_iterator lb = std::lower_bound(local_starts.begin(), local_starts.end(), (std::size_t) i);
|
||||
return ((SizeType)(*lb) == i ? lb : --lb) - local_starts.begin();
|
||||
}
|
||||
|
||||
// Find the starting index for processor with the given id
|
||||
template<typename ID>
|
||||
std::size_t start(ID id) const
|
||||
{
|
||||
return local_starts[id];
|
||||
}
|
||||
|
||||
// Find the local index for the ith global element
|
||||
template<typename SizeType>
|
||||
SizeType local(SizeType i) const
|
||||
{
|
||||
SizeType owner = (*this)(i);
|
||||
return i - start(owner);
|
||||
}
|
||||
|
||||
// Returns the global index of local element i
|
||||
template<typename SizeType>
|
||||
SizeType global(SizeType i) const
|
||||
{ return global(id, i); }
|
||||
|
||||
// Returns the global index of the ith local element on processor id
|
||||
template<typename ProcessID, typename SizeType>
|
||||
SizeType global(ProcessID id, SizeType i) const
|
||||
{ return i + start(id); }
|
||||
|
||||
private:
|
||||
std::size_t id; //< The ID number of this processor
|
||||
std::size_t p; //< The number of processors
|
||||
std::size_t n; //< The size of the problem space
|
||||
std::vector<std::size_t> local_sizes; //< The sizes of all blocks
|
||||
std::vector<std::size_t> local_starts; //< Lowest global index of each block
|
||||
};
|
||||
|
||||
|
||||
struct oned_block_cyclic
|
||||
{
|
||||
template<typename LinearProcessGroup>
|
||||
explicit oned_block_cyclic(const LinearProcessGroup& pg, std::size_t size)
|
||||
: id(process_id(pg)), p(num_processes(pg)), size(size) { }
|
||||
|
||||
template<typename SizeType>
|
||||
SizeType block_size(SizeType n) const
|
||||
{
|
||||
return block_size(id, n);
|
||||
}
|
||||
|
||||
template<typename SizeType, typename ProcessID>
|
||||
SizeType block_size(ProcessID id, SizeType n) const
|
||||
{
|
||||
SizeType all_blocks = n / size;
|
||||
SizeType extra_elements = n % size;
|
||||
SizeType everyone_gets = all_blocks / p;
|
||||
SizeType extra_blocks = all_blocks % p;
|
||||
SizeType my_blocks = everyone_gets + (p < extra_blocks? 1 : 0);
|
||||
SizeType my_elements = my_blocks * size
|
||||
+ (p == extra_blocks? extra_elements : 0);
|
||||
return my_elements;
|
||||
}
|
||||
|
||||
template<typename SizeType>
|
||||
SizeType operator()(SizeType i) const
|
||||
{
|
||||
return (i / size) % p;
|
||||
}
|
||||
|
||||
template<typename SizeType>
|
||||
SizeType local(SizeType i) const
|
||||
{
|
||||
return ((i / size) / p) * size + i % size;
|
||||
}
|
||||
|
||||
template<typename SizeType>
|
||||
SizeType global(SizeType i) const
|
||||
{ return global(id, i); }
|
||||
|
||||
template<typename ProcessID, typename SizeType>
|
||||
SizeType global(ProcessID id, SizeType i) const
|
||||
{
|
||||
return ((i / size) * p + id) * size + i % size;
|
||||
}
|
||||
|
||||
private:
|
||||
std::size_t id; //< The ID number of this processor
|
||||
std::size_t p; //< The number of processors
|
||||
std::size_t size; //< Block size
|
||||
};
|
||||
|
||||
struct twod_block_cyclic
|
||||
{
|
||||
template<typename LinearProcessGroup>
|
||||
explicit twod_block_cyclic(const LinearProcessGroup& pg,
|
||||
std::size_t block_rows, std::size_t block_columns,
|
||||
std::size_t data_columns_per_row)
|
||||
: id(process_id(pg)), p(num_processes(pg)),
|
||||
block_rows(block_rows), block_columns(block_columns),
|
||||
data_columns_per_row(data_columns_per_row)
|
||||
{ }
|
||||
|
||||
template<typename SizeType>
|
||||
SizeType block_size(SizeType n) const
|
||||
{
|
||||
return block_size(id, n);
|
||||
}
|
||||
|
||||
template<typename SizeType, typename ProcessID>
|
||||
SizeType block_size(ProcessID id, SizeType n) const
|
||||
{
|
||||
// TBD: This is really lame :)
|
||||
int result = -1;
|
||||
while (n > 0) {
|
||||
--n;
|
||||
if ((*this)(n) == id && (int)local(n) > result) result = local(n);
|
||||
}
|
||||
++result;
|
||||
|
||||
// std::cerr << "Block size of id " << id << " is " << result << std::endl;
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename SizeType>
|
||||
SizeType operator()(SizeType i) const
|
||||
{
|
||||
SizeType result = get_block_num(i) % p;
|
||||
// std::cerr << "Item " << i << " goes on processor " << result << std::endl;
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename SizeType>
|
||||
SizeType local(SizeType i) const
|
||||
{
|
||||
// Compute the start of the block
|
||||
std::size_t block_num = get_block_num(i);
|
||||
// std::cerr << "Item " << i << " is in block #" << block_num << std::endl;
|
||||
|
||||
std::size_t local_block_num = block_num / p;
|
||||
std::size_t block_start = local_block_num * block_rows * block_columns;
|
||||
|
||||
// Compute the offset into the block
|
||||
std::size_t data_row = i / data_columns_per_row;
|
||||
std::size_t data_col = i % data_columns_per_row;
|
||||
std::size_t block_offset = (data_row % block_rows) * block_columns
|
||||
+ (data_col % block_columns);
|
||||
|
||||
// std::cerr << "Item " << i << " maps to local index " << block_start+block_offset << std::endl;
|
||||
return block_start + block_offset;
|
||||
}
|
||||
|
||||
template<typename SizeType>
|
||||
SizeType global(SizeType i) const
|
||||
{
|
||||
// Compute the (global) block in which this element resides
|
||||
SizeType local_block_num = i / (block_rows * block_columns);
|
||||
SizeType block_offset = i % (block_rows * block_columns);
|
||||
SizeType block_num = local_block_num * p + id;
|
||||
|
||||
// Compute the position of the start of the block (globally)
|
||||
SizeType block_start = block_num * block_rows * block_columns;
|
||||
|
||||
std::cerr << "Block " << block_num << " starts at index " << block_start
|
||||
<< std::endl;
|
||||
|
||||
// Compute the row and column of this block
|
||||
SizeType block_row = block_num / (data_columns_per_row / block_columns);
|
||||
SizeType block_col = block_num % (data_columns_per_row / block_columns);
|
||||
|
||||
SizeType row_in_block = block_offset / block_columns;
|
||||
SizeType col_in_block = block_offset % block_columns;
|
||||
|
||||
std::cerr << "Local index " << i << " is in block at row " << block_row
|
||||
<< ", column " << block_col << ", in-block row " << row_in_block
|
||||
<< ", in-block col " << col_in_block << std::endl;
|
||||
|
||||
SizeType result = block_row * block_rows + block_col * block_columns
|
||||
+ row_in_block * block_rows + col_in_block;
|
||||
|
||||
|
||||
std::cerr << "global(" << i << "@" << id << ") = " << result
|
||||
<< " =? " << local(result) << std::endl;
|
||||
BOOST_ASSERT(i == local(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
template<typename SizeType>
|
||||
std::size_t get_block_num(SizeType i) const
|
||||
{
|
||||
std::size_t data_row = i / data_columns_per_row;
|
||||
std::size_t data_col = i % data_columns_per_row;
|
||||
std::size_t block_row = data_row / block_rows;
|
||||
std::size_t block_col = data_col / block_columns;
|
||||
std::size_t blocks_in_row = data_columns_per_row / block_columns;
|
||||
std::size_t block_num = block_col * blocks_in_row + block_row;
|
||||
return block_num;
|
||||
}
|
||||
|
||||
std::size_t id; //< The ID number of this processor
|
||||
std::size_t p; //< The number of processors
|
||||
std::size_t block_rows; //< The # of rows in each block
|
||||
std::size_t block_columns; //< The # of columns in each block
|
||||
std::size_t data_columns_per_row; //< The # of columns per row of data
|
||||
};
|
||||
|
||||
class twod_random
|
||||
{
|
||||
template<typename RandomNumberGen>
|
||||
struct random_int
|
||||
{
|
||||
explicit random_int(RandomNumberGen& gen) : gen(gen) { }
|
||||
|
||||
template<typename T>
|
||||
T operator()(T n) const
|
||||
{
|
||||
uniform_int<T> distrib(0, n-1);
|
||||
return distrib(gen);
|
||||
}
|
||||
|
||||
private:
|
||||
RandomNumberGen& gen;
|
||||
};
|
||||
|
||||
public:
|
||||
template<typename LinearProcessGroup, typename RandomNumberGen>
|
||||
explicit twod_random(const LinearProcessGroup& pg,
|
||||
std::size_t block_rows, std::size_t block_columns,
|
||||
std::size_t data_columns_per_row,
|
||||
std::size_t n,
|
||||
RandomNumberGen& gen)
|
||||
: id(process_id(pg)), p(num_processes(pg)),
|
||||
block_rows(block_rows), block_columns(block_columns),
|
||||
data_columns_per_row(data_columns_per_row),
|
||||
global_to_local(n / (block_rows * block_columns))
|
||||
{
|
||||
std::copy(make_counting_iterator(std::size_t(0)),
|
||||
make_counting_iterator(global_to_local.size()),
|
||||
global_to_local.begin());
|
||||
|
||||
random_int<RandomNumberGen> rand(gen);
|
||||
std::random_shuffle(global_to_local.begin(), global_to_local.end(), rand);
|
||||
}
|
||||
|
||||
template<typename SizeType>
|
||||
SizeType block_size(SizeType n) const
|
||||
{
|
||||
return block_size(id, n);
|
||||
}
|
||||
|
||||
template<typename SizeType, typename ProcessID>
|
||||
SizeType block_size(ProcessID id, SizeType n) const
|
||||
{
|
||||
// TBD: This is really lame :)
|
||||
int result = -1;
|
||||
while (n > 0) {
|
||||
--n;
|
||||
if ((*this)(n) == id && (int)local(n) > result) result = local(n);
|
||||
}
|
||||
++result;
|
||||
|
||||
// std::cerr << "Block size of id " << id << " is " << result << std::endl;
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename SizeType>
|
||||
SizeType operator()(SizeType i) const
|
||||
{
|
||||
SizeType result = get_block_num(i) % p;
|
||||
// std::cerr << "Item " << i << " goes on processor " << result << std::endl;
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename SizeType>
|
||||
SizeType local(SizeType i) const
|
||||
{
|
||||
// Compute the start of the block
|
||||
std::size_t block_num = get_block_num(i);
|
||||
// std::cerr << "Item " << i << " is in block #" << block_num << std::endl;
|
||||
|
||||
std::size_t local_block_num = block_num / p;
|
||||
std::size_t block_start = local_block_num * block_rows * block_columns;
|
||||
|
||||
// Compute the offset into the block
|
||||
std::size_t data_row = i / data_columns_per_row;
|
||||
std::size_t data_col = i % data_columns_per_row;
|
||||
std::size_t block_offset = (data_row % block_rows) * block_columns
|
||||
+ (data_col % block_columns);
|
||||
|
||||
// std::cerr << "Item " << i << " maps to local index " << block_start+block_offset << std::endl;
|
||||
return block_start + block_offset;
|
||||
}
|
||||
|
||||
private:
|
||||
template<typename SizeType>
|
||||
std::size_t get_block_num(SizeType i) const
|
||||
{
|
||||
std::size_t data_row = i / data_columns_per_row;
|
||||
std::size_t data_col = i % data_columns_per_row;
|
||||
std::size_t block_row = data_row / block_rows;
|
||||
std::size_t block_col = data_col / block_columns;
|
||||
std::size_t blocks_in_row = data_columns_per_row / block_columns;
|
||||
std::size_t block_num = block_col * blocks_in_row + block_row;
|
||||
return global_to_local[block_num];
|
||||
}
|
||||
|
||||
std::size_t id; //< The ID number of this processor
|
||||
std::size_t p; //< The number of processors
|
||||
std::size_t block_rows; //< The # of rows in each block
|
||||
std::size_t block_columns; //< The # of columns in each block
|
||||
std::size_t data_columns_per_row; //< The # of columns per row of data
|
||||
std::vector<std::size_t> global_to_local;
|
||||
};
|
||||
|
||||
class random_distribution
|
||||
{
|
||||
template<typename RandomNumberGen>
|
||||
struct random_int
|
||||
{
|
||||
explicit random_int(RandomNumberGen& gen) : gen(gen) { }
|
||||
|
||||
template<typename T>
|
||||
T operator()(T n) const
|
||||
{
|
||||
uniform_int<T> distrib(0, n-1);
|
||||
return distrib(gen);
|
||||
}
|
||||
|
||||
private:
|
||||
RandomNumberGen& gen;
|
||||
};
|
||||
|
||||
public:
|
||||
template<typename LinearProcessGroup, typename RandomNumberGen>
|
||||
random_distribution(const LinearProcessGroup& pg, RandomNumberGen& gen,
|
||||
std::size_t n)
|
||||
: base(pg, n), local_to_global(n), global_to_local(n)
|
||||
{
|
||||
std::copy(make_counting_iterator(std::size_t(0)),
|
||||
make_counting_iterator(n),
|
||||
local_to_global.begin());
|
||||
|
||||
random_int<RandomNumberGen> rand(gen);
|
||||
std::random_shuffle(local_to_global.begin(), local_to_global.end(), rand);
|
||||
|
||||
|
||||
for (std::vector<std::size_t>::size_type i = 0; i < n; ++i)
|
||||
global_to_local[local_to_global[i]] = i;
|
||||
}
|
||||
|
||||
template<typename SizeType>
|
||||
SizeType block_size(SizeType n) const
|
||||
{ return base.block_size(n); }
|
||||
|
||||
template<typename SizeType, typename ProcessID>
|
||||
SizeType block_size(ProcessID id, SizeType n) const
|
||||
{ return base.block_size(id, n); }
|
||||
|
||||
template<typename SizeType>
|
||||
SizeType operator()(SizeType i) const
|
||||
{
|
||||
return base(global_to_local[i]);
|
||||
}
|
||||
|
||||
template<typename SizeType>
|
||||
SizeType local(SizeType i) const
|
||||
{
|
||||
return base.local(global_to_local[i]);
|
||||
}
|
||||
|
||||
template<typename ProcessID, typename SizeType>
|
||||
SizeType global(ProcessID p, SizeType i) const
|
||||
{
|
||||
return local_to_global[base.global(p, i)];
|
||||
}
|
||||
|
||||
template<typename SizeType>
|
||||
SizeType global(SizeType i) const
|
||||
{
|
||||
return local_to_global[base.global(i)];
|
||||
}
|
||||
|
||||
private:
|
||||
block base;
|
||||
std::vector<std::size_t> local_to_global;
|
||||
std::vector<std::size_t> global_to_local;
|
||||
};
|
||||
|
||||
} } // end namespace boost::parallel
|
||||
|
||||
#endif // BOOST_PARALLEL_DISTRIBUTION_HPP
|
||||
|
40
patched/graph/parallel/distribution.patch
Normal file
40
patched/graph/parallel/distribution.patch
Normal file
@ -0,0 +1,40 @@
|
||||
Index: .
|
||||
===================================================================
|
||||
--- . (revision 86520)
|
||||
+++ . (working copy)
|
||||
@@ -22,7 +22,7 @@
|
||||
#include <boost/iterator/counting_iterator.hpp>
|
||||
#include <boost/random/uniform_int.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
-#include <typeinfo>
|
||||
+#include <boost/type_index/type_info.hpp>
|
||||
|
||||
namespace boost { namespace parallel {
|
||||
|
||||
@@ -71,7 +71,7 @@
|
||||
|
||||
virtual void* address() { return &distribution_; }
|
||||
virtual const void* address() const { return &distribution_; }
|
||||
- virtual const std::type_info& type() const { return typeid(Distribution); }
|
||||
+ virtual const boost::type_info& type() const { return boost::type_id<Distribution>(); }
|
||||
|
||||
private:
|
||||
Distribution distribution_;
|
||||
@@ -106,7 +106,7 @@
|
||||
template<typename T>
|
||||
T* as()
|
||||
{
|
||||
- if (distribution_->type() == typeid(T))
|
||||
+ if (distribution_->type() == boost::type_id<T>())
|
||||
return static_cast<T*>(distribution_->address());
|
||||
else
|
||||
return 0;
|
||||
@@ -115,7 +115,7 @@
|
||||
template<typename T>
|
||||
const T* as() const
|
||||
{
|
||||
- if (distribution_->type() == typeid(T))
|
||||
+ if (distribution_->type() == boost::type_id<T>())
|
||||
return static_cast<T*>(distribution_->address());
|
||||
else
|
||||
return 0;
|
@ -1,163 +0,0 @@
|
||||
// Copyright John Maddock 2010.
|
||||
// Use, modification and distribution are subject to the
|
||||
// Boost Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_MATH_CONSTANTS_INFO_INCLUDED
|
||||
#define BOOST_MATH_CONSTANTS_INFO_INCLUDED
|
||||
|
||||
#include <boost/math/constants/constants.hpp>
|
||||
#include <boost/type_index.hpp>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
|
||||
namespace boost{ namespace math{ namespace constants{
|
||||
|
||||
namespace detail{
|
||||
|
||||
template <class T>
|
||||
const char* nameof(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(T))
|
||||
{
|
||||
return type_id<T>().name_demangled();
|
||||
}
|
||||
template <>
|
||||
const char* nameof<float>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(float))
|
||||
{
|
||||
return "float";
|
||||
}
|
||||
template <>
|
||||
const char* nameof<double>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(double))
|
||||
{
|
||||
return "double";
|
||||
}
|
||||
template <>
|
||||
const char* nameof<long double>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(long double))
|
||||
{
|
||||
return "long double";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
void print_info_on_type(std::ostream& os = std::cout BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE_SPEC(T) BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE_SPEC(Policy))
|
||||
{
|
||||
using detail::nameof;
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4127)
|
||||
#endif
|
||||
os <<
|
||||
"Information on the Implementation and Handling of \n"
|
||||
"Mathematical Constants for Type " << nameof<T>() <<
|
||||
"\n\n"
|
||||
"Checking for std::numeric_limits<" << nameof<T>() << "> specialisation: " <<
|
||||
(std::numeric_limits<T>::is_specialized ? "yes" : "no") << std::endl;
|
||||
if(std::numeric_limits<T>::is_specialized)
|
||||
{
|
||||
os <<
|
||||
"std::numeric_limits<" << nameof<T>() << ">::digits reports that the radix is " << std::numeric_limits<T>::radix << ".\n";
|
||||
if (std::numeric_limits<T>::radix == 2)
|
||||
{
|
||||
os <<
|
||||
"std::numeric_limits<" << nameof<T>() << ">::digits reports that the precision is \n" << std::numeric_limits<T>::digits << " binary digits.\n";
|
||||
}
|
||||
else if (std::numeric_limits<T>::radix == 10)
|
||||
{
|
||||
os <<
|
||||
"std::numeric_limits<" << nameof<T>() << ">::digits reports that the precision is \n" << std::numeric_limits<T>::digits10 << " decimal digits.\n";
|
||||
os <<
|
||||
"std::numeric_limits<" << nameof<T>() << ">::digits reports that the precision is \n"
|
||||
<< std::numeric_limits<T>::digits * 1000L /301L << " binary digits.\n"; // divide by log2(10) - about 3 bits per decimal digit.
|
||||
}
|
||||
else
|
||||
{
|
||||
os << "Unknown radix = " << std::numeric_limits<T>::radix << "\n";
|
||||
}
|
||||
}
|
||||
typedef typename boost::math::policies::precision<T, Policy>::type precision_type;
|
||||
if(precision_type::value)
|
||||
{
|
||||
if (std::numeric_limits<T>::radix == 2)
|
||||
{
|
||||
os <<
|
||||
"boost::math::policies::precision<" << nameof<T>() << ", " << nameof<Policy>() << " reports that the compile time precision is \n" << precision_type::value << " binary digits.\n";
|
||||
}
|
||||
else if (std::numeric_limits<T>::radix == 10)
|
||||
{
|
||||
os <<
|
||||
"boost::math::policies::precision<" << nameof<T>() << ", " << nameof<Policy>() << " reports that the compile time precision is \n" << precision_type::value << " binary digits.\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
os << "Unknown radix = " << std::numeric_limits<T>::radix << "\n";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
os <<
|
||||
"boost::math::policies::precision<" << nameof<T>() << ", Policy> \n"
|
||||
"reports that there is no compile type precision available.\n"
|
||||
"boost::math::tools::digits<" << nameof<T>() << ">() \n"
|
||||
"reports that the current runtime precision is \n" <<
|
||||
boost::math::tools::digits<T>() << " binary digits.\n";
|
||||
}
|
||||
|
||||
typedef typename construction_traits<T, Policy>::type construction_type;
|
||||
|
||||
switch(construction_type::value)
|
||||
{
|
||||
case 0:
|
||||
os <<
|
||||
"No compile time precision is available, the construction method \n"
|
||||
"will be decided at runtime and results will not be cached \n"
|
||||
"- this may lead to poor runtime performance.\n"
|
||||
"Current runtime precision indicates that\n";
|
||||
if(boost::math::tools::digits<T>() > max_string_digits)
|
||||
{
|
||||
os << "the constant will be recalculated on each call.\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
os << "the constant will be constructed from a string on each call.\n";
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
os <<
|
||||
"The constant will be constructed from a float.\n";
|
||||
break;
|
||||
case 2:
|
||||
os <<
|
||||
"The constant will be constructed from a double.\n";
|
||||
break;
|
||||
case 3:
|
||||
os <<
|
||||
"The constant will be constructed from a long double.\n";
|
||||
break;
|
||||
case 4:
|
||||
os <<
|
||||
"The constant will be constructed from a string (and the result cached).\n";
|
||||
break;
|
||||
default:
|
||||
os <<
|
||||
"The constant will be calculated (and the result cached).\n";
|
||||
break;
|
||||
}
|
||||
os << std::endl;
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void print_info_on_type(std::ostream& os = std::cout BOOST_MATH_APPEND_EXPLICIT_TEMPLATE_TYPE_SPEC(T))
|
||||
{
|
||||
print_info_on_type<T, boost::math::policies::policy<> >(os);
|
||||
}
|
||||
|
||||
}}} // namespaces
|
||||
|
||||
#endif // BOOST_MATH_CONSTANTS_INFO_INCLUDED
|
@ -1,488 +0,0 @@
|
||||
// Copyright 2008 Gautam Sewani
|
||||
// Copyright 2008 John Maddock
|
||||
//
|
||||
// Use, modification and distribution are subject to the
|
||||
// Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt
|
||||
// or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_MATH_DISTRIBUTIONS_DETAIL_HG_PDF_HPP
|
||||
#define BOOST_MATH_DISTRIBUTIONS_DETAIL_HG_PDF_HPP
|
||||
|
||||
#include <boost/math/constants/constants.hpp>
|
||||
#include <boost/math/special_functions/lanczos.hpp>
|
||||
#include <boost/math/special_functions/gamma.hpp>
|
||||
#include <boost/math/special_functions/pow.hpp>
|
||||
#include <boost/math/special_functions/prime.hpp>
|
||||
#include <boost/math/policies/error_handling.hpp>
|
||||
|
||||
#ifdef BOOST_MATH_INSTRUMENT
|
||||
#include <boost/type_index.hpp>
|
||||
#endif
|
||||
|
||||
namespace boost{ namespace math{ namespace detail{
|
||||
|
||||
template <class T, class Func>
|
||||
void bubble_down_one(T* first, T* last, Func f)
|
||||
{
|
||||
using std::swap;
|
||||
T* next = first;
|
||||
++next;
|
||||
while((next != last) && (!f(*first, *next)))
|
||||
{
|
||||
swap(*first, *next);
|
||||
++first;
|
||||
++next;
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
struct sort_functor
|
||||
{
|
||||
sort_functor(const T* exponents) : m_exponents(exponents){}
|
||||
bool operator()(int i, int j)
|
||||
{
|
||||
return m_exponents[i] > m_exponents[j];
|
||||
}
|
||||
private:
|
||||
const T* m_exponents;
|
||||
};
|
||||
|
||||
template <class T, class Lanczos, class Policy>
|
||||
T hypergeometric_pdf_lanczos_imp(T /*dummy*/, unsigned x, unsigned r, unsigned n, unsigned N, const Lanczos&, const Policy&)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
|
||||
BOOST_MATH_INSTRUMENT_FPU
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(x);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(r);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(n);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(N);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(type_id<Lanczos>().name_demangled());
|
||||
|
||||
T bases[9] = {
|
||||
T(n) + Lanczos::g() + 0.5f,
|
||||
T(r) + Lanczos::g() + 0.5f,
|
||||
T(N - n) + Lanczos::g() + 0.5f,
|
||||
T(N - r) + Lanczos::g() + 0.5f,
|
||||
1 / (T(N) + Lanczos::g() + 0.5f),
|
||||
1 / (T(x) + Lanczos::g() + 0.5f),
|
||||
1 / (T(n - x) + Lanczos::g() + 0.5f),
|
||||
1 / (T(r - x) + Lanczos::g() + 0.5f),
|
||||
1 / (T(N - n - r + x) + Lanczos::g() + 0.5f)
|
||||
};
|
||||
T exponents[9] = {
|
||||
n + T(0.5f),
|
||||
r + T(0.5f),
|
||||
N - n + T(0.5f),
|
||||
N - r + T(0.5f),
|
||||
N + T(0.5f),
|
||||
x + T(0.5f),
|
||||
n - x + T(0.5f),
|
||||
r - x + T(0.5f),
|
||||
N - n - r + x + T(0.5f)
|
||||
};
|
||||
int base_e_factors[9] = {
|
||||
-1, -1, -1, -1, 1, 1, 1, 1, 1
|
||||
};
|
||||
int sorted_indexes[9] = {
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8
|
||||
};
|
||||
#ifdef BOOST_MATH_INSTRUMENT
|
||||
BOOST_MATH_INSTRUMENT_FPU
|
||||
for(unsigned i = 0; i < 9; ++i)
|
||||
{
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(i);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(bases[i]);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(exponents[i]);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(base_e_factors[i]);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(sorted_indexes[i]);
|
||||
}
|
||||
#endif
|
||||
std::sort(sorted_indexes, sorted_indexes + 9, sort_functor<T>(exponents));
|
||||
#ifdef BOOST_MATH_INSTRUMENT
|
||||
BOOST_MATH_INSTRUMENT_FPU
|
||||
for(unsigned i = 0; i < 9; ++i)
|
||||
{
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(i);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(bases[i]);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(exponents[i]);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(base_e_factors[i]);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(sorted_indexes[i]);
|
||||
}
|
||||
#endif
|
||||
|
||||
do{
|
||||
exponents[sorted_indexes[0]] -= exponents[sorted_indexes[1]];
|
||||
bases[sorted_indexes[1]] *= bases[sorted_indexes[0]];
|
||||
if((bases[sorted_indexes[1]] < tools::min_value<T>()) && (exponents[sorted_indexes[1]] != 0))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
base_e_factors[sorted_indexes[1]] += base_e_factors[sorted_indexes[0]];
|
||||
bubble_down_one(sorted_indexes, sorted_indexes + 9, sort_functor<T>(exponents));
|
||||
|
||||
#ifdef BOOST_MATH_INSTRUMENT
|
||||
for(unsigned i = 0; i < 9; ++i)
|
||||
{
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(i);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(bases[i]);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(exponents[i]);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(base_e_factors[i]);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(sorted_indexes[i]);
|
||||
}
|
||||
#endif
|
||||
}while(exponents[sorted_indexes[1]] > 1);
|
||||
|
||||
//
|
||||
// Combine equal powers:
|
||||
//
|
||||
int j = 8;
|
||||
while(exponents[sorted_indexes[j]] == 0) --j;
|
||||
while(j)
|
||||
{
|
||||
while(j && (exponents[sorted_indexes[j-1]] == exponents[sorted_indexes[j]]))
|
||||
{
|
||||
bases[sorted_indexes[j-1]] *= bases[sorted_indexes[j]];
|
||||
exponents[sorted_indexes[j]] = 0;
|
||||
base_e_factors[sorted_indexes[j-1]] += base_e_factors[sorted_indexes[j]];
|
||||
bubble_down_one(sorted_indexes + j, sorted_indexes + 9, sort_functor<T>(exponents));
|
||||
--j;
|
||||
}
|
||||
--j;
|
||||
|
||||
#ifdef BOOST_MATH_INSTRUMENT
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(j);
|
||||
for(unsigned i = 0; i < 9; ++i)
|
||||
{
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(i);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(bases[i]);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(exponents[i]);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(base_e_factors[i]);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(sorted_indexes[i]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef BOOST_MATH_INSTRUMENT
|
||||
BOOST_MATH_INSTRUMENT_FPU
|
||||
for(unsigned i = 0; i < 9; ++i)
|
||||
{
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(i);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(bases[i]);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(exponents[i]);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(base_e_factors[i]);
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(sorted_indexes[i]);
|
||||
}
|
||||
#endif
|
||||
|
||||
T result;
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(bases[sorted_indexes[0]] * exp(static_cast<T>(base_e_factors[sorted_indexes[0]])));
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(exponents[sorted_indexes[0]]);
|
||||
{
|
||||
BOOST_FPU_EXCEPTION_GUARD
|
||||
result = pow(bases[sorted_indexes[0]] * exp(static_cast<T>(base_e_factors[sorted_indexes[0]])), exponents[sorted_indexes[0]]);
|
||||
}
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(result);
|
||||
for(unsigned i = 1; (i < 9) && (exponents[sorted_indexes[i]] > 0); ++i)
|
||||
{
|
||||
BOOST_FPU_EXCEPTION_GUARD
|
||||
if(result < tools::min_value<T>())
|
||||
return 0; // short circuit further evaluation
|
||||
if(exponents[sorted_indexes[i]] == 1)
|
||||
result *= bases[sorted_indexes[i]] * exp(static_cast<T>(base_e_factors[sorted_indexes[i]]));
|
||||
else if(exponents[sorted_indexes[i]] == 0.5f)
|
||||
result *= sqrt(bases[sorted_indexes[i]] * exp(static_cast<T>(base_e_factors[sorted_indexes[i]])));
|
||||
else
|
||||
result *= pow(bases[sorted_indexes[i]] * exp(static_cast<T>(base_e_factors[sorted_indexes[i]])), exponents[sorted_indexes[i]]);
|
||||
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(result);
|
||||
}
|
||||
|
||||
result *= Lanczos::lanczos_sum_expG_scaled(static_cast<T>(n + 1))
|
||||
* Lanczos::lanczos_sum_expG_scaled(static_cast<T>(r + 1))
|
||||
* Lanczos::lanczos_sum_expG_scaled(static_cast<T>(N - n + 1))
|
||||
* Lanczos::lanczos_sum_expG_scaled(static_cast<T>(N - r + 1))
|
||||
/
|
||||
( Lanczos::lanczos_sum_expG_scaled(static_cast<T>(N + 1))
|
||||
* Lanczos::lanczos_sum_expG_scaled(static_cast<T>(x + 1))
|
||||
* Lanczos::lanczos_sum_expG_scaled(static_cast<T>(n - x + 1))
|
||||
* Lanczos::lanczos_sum_expG_scaled(static_cast<T>(r - x + 1))
|
||||
* Lanczos::lanczos_sum_expG_scaled(static_cast<T>(N - n - r + x + 1)));
|
||||
|
||||
BOOST_MATH_INSTRUMENT_VARIABLE(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
T hypergeometric_pdf_lanczos_imp(T /*dummy*/, unsigned x, unsigned r, unsigned n, unsigned N, const boost::math::lanczos::undefined_lanczos&, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
return exp(
|
||||
boost::math::lgamma(T(n + 1), pol)
|
||||
+ boost::math::lgamma(T(r + 1), pol)
|
||||
+ boost::math::lgamma(T(N - n + 1), pol)
|
||||
+ boost::math::lgamma(T(N - r + 1), pol)
|
||||
- boost::math::lgamma(T(N + 1), pol)
|
||||
- boost::math::lgamma(T(x + 1), pol)
|
||||
- boost::math::lgamma(T(n - x + 1), pol)
|
||||
- boost::math::lgamma(T(r - x + 1), pol)
|
||||
- boost::math::lgamma(T(N - n - r + x + 1), pol));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T integer_power(const T& x, int ex)
|
||||
{
|
||||
if(ex < 0)
|
||||
return 1 / integer_power(x, -ex);
|
||||
switch(ex)
|
||||
{
|
||||
case 0:
|
||||
return 1;
|
||||
case 1:
|
||||
return x;
|
||||
case 2:
|
||||
return x * x;
|
||||
case 3:
|
||||
return x * x * x;
|
||||
case 4:
|
||||
return boost::math::pow<4>(x);
|
||||
case 5:
|
||||
return boost::math::pow<5>(x);
|
||||
case 6:
|
||||
return boost::math::pow<6>(x);
|
||||
case 7:
|
||||
return boost::math::pow<7>(x);
|
||||
case 8:
|
||||
return boost::math::pow<8>(x);
|
||||
}
|
||||
BOOST_MATH_STD_USING
|
||||
#ifdef __SUNPRO_CC
|
||||
return pow(x, T(ex));
|
||||
#else
|
||||
return pow(x, ex);
|
||||
#endif
|
||||
}
|
||||
template <class T>
|
||||
struct hypergeometric_pdf_prime_loop_result_entry
|
||||
{
|
||||
T value;
|
||||
const hypergeometric_pdf_prime_loop_result_entry* next;
|
||||
};
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4510 4512 4610)
|
||||
#endif
|
||||
|
||||
struct hypergeometric_pdf_prime_loop_data
|
||||
{
|
||||
const unsigned x;
|
||||
const unsigned r;
|
||||
const unsigned n;
|
||||
const unsigned N;
|
||||
unsigned prime_index;
|
||||
unsigned current_prime;
|
||||
};
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
template <class T>
|
||||
T hypergeometric_pdf_prime_loop_imp(hypergeometric_pdf_prime_loop_data& data, hypergeometric_pdf_prime_loop_result_entry<T>& result)
|
||||
{
|
||||
while(data.current_prime <= data.N)
|
||||
{
|
||||
unsigned base = data.current_prime;
|
||||
int prime_powers = 0;
|
||||
while(base <= data.N)
|
||||
{
|
||||
prime_powers += data.n / base;
|
||||
prime_powers += data.r / base;
|
||||
prime_powers += (data.N - data.n) / base;
|
||||
prime_powers += (data.N - data.r) / base;
|
||||
prime_powers -= data.N / base;
|
||||
prime_powers -= data.x / base;
|
||||
prime_powers -= (data.n - data.x) / base;
|
||||
prime_powers -= (data.r - data.x) / base;
|
||||
prime_powers -= (data.N - data.n - data.r + data.x) / base;
|
||||
base *= data.current_prime;
|
||||
}
|
||||
if(prime_powers)
|
||||
{
|
||||
T p = integer_power<T>(data.current_prime, prime_powers);
|
||||
if((p > 1) && (tools::max_value<T>() / p < result.value))
|
||||
{
|
||||
//
|
||||
// The next calculation would overflow, use recursion
|
||||
// to sidestep the issue:
|
||||
//
|
||||
hypergeometric_pdf_prime_loop_result_entry<T> t = { p, &result };
|
||||
data.current_prime = prime(++data.prime_index);
|
||||
return hypergeometric_pdf_prime_loop_imp<T>(data, t);
|
||||
}
|
||||
if((p < 1) && (tools::min_value<T>() / p > result.value))
|
||||
{
|
||||
//
|
||||
// The next calculation would underflow, use recursion
|
||||
// to sidestep the issue:
|
||||
//
|
||||
hypergeometric_pdf_prime_loop_result_entry<T> t = { p, &result };
|
||||
data.current_prime = prime(++data.prime_index);
|
||||
return hypergeometric_pdf_prime_loop_imp<T>(data, t);
|
||||
}
|
||||
result.value *= p;
|
||||
}
|
||||
data.current_prime = prime(++data.prime_index);
|
||||
}
|
||||
//
|
||||
// When we get to here we have run out of prime factors,
|
||||
// the overall result is the product of all the partial
|
||||
// results we have accumulated on the stack so far, these
|
||||
// are in a linked list starting with "data.head" and ending
|
||||
// with "result".
|
||||
//
|
||||
// All that remains is to multiply them together, taking
|
||||
// care not to overflow or underflow.
|
||||
//
|
||||
// Enumerate partial results >= 1 in variable i
|
||||
// and partial results < 1 in variable j:
|
||||
//
|
||||
hypergeometric_pdf_prime_loop_result_entry<T> const *i, *j;
|
||||
i = &result;
|
||||
while(i && i->value < 1)
|
||||
i = i->next;
|
||||
j = &result;
|
||||
while(j && j->value >= 1)
|
||||
j = j->next;
|
||||
|
||||
T prod = 1;
|
||||
|
||||
while(i || j)
|
||||
{
|
||||
while(i && ((prod <= 1) || (j == 0)))
|
||||
{
|
||||
prod *= i->value;
|
||||
i = i->next;
|
||||
while(i && i->value < 1)
|
||||
i = i->next;
|
||||
}
|
||||
while(j && ((prod >= 1) || (i == 0)))
|
||||
{
|
||||
prod *= j->value;
|
||||
j = j->next;
|
||||
while(j && j->value >= 1)
|
||||
j = j->next;
|
||||
}
|
||||
}
|
||||
|
||||
return prod;
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline T hypergeometric_pdf_prime_imp(unsigned x, unsigned r, unsigned n, unsigned N, const Policy&)
|
||||
{
|
||||
hypergeometric_pdf_prime_loop_result_entry<T> result = { 1, 0 };
|
||||
hypergeometric_pdf_prime_loop_data data = { x, r, n, N, 0, prime(0) };
|
||||
return hypergeometric_pdf_prime_loop_imp<T>(data, result);
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
T hypergeometric_pdf_factorial_imp(unsigned x, unsigned r, unsigned n, unsigned N, const Policy&)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
BOOST_ASSERT(N < boost::math::max_factorial<T>::value);
|
||||
T result = boost::math::unchecked_factorial<T>(n);
|
||||
T num[3] = {
|
||||
boost::math::unchecked_factorial<T>(r),
|
||||
boost::math::unchecked_factorial<T>(N - n),
|
||||
boost::math::unchecked_factorial<T>(N - r)
|
||||
};
|
||||
T denom[5] = {
|
||||
boost::math::unchecked_factorial<T>(N),
|
||||
boost::math::unchecked_factorial<T>(x),
|
||||
boost::math::unchecked_factorial<T>(n - x),
|
||||
boost::math::unchecked_factorial<T>(r - x),
|
||||
boost::math::unchecked_factorial<T>(N - n - r + x)
|
||||
};
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
while((i < 3) || (j < 5))
|
||||
{
|
||||
while((j < 5) && ((result >= 1) || (i >= 3)))
|
||||
{
|
||||
result /= denom[j];
|
||||
++j;
|
||||
}
|
||||
while((i < 3) && ((result <= 1) || (j >= 5)))
|
||||
{
|
||||
result *= num[i];
|
||||
++i;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
template <class T, class Policy>
|
||||
inline typename tools::promote_args<T>::type
|
||||
hypergeometric_pdf(unsigned x, unsigned r, unsigned n, unsigned N, const Policy&)
|
||||
{
|
||||
BOOST_FPU_EXCEPTION_GUARD
|
||||
typedef typename tools::promote_args<T>::type result_type;
|
||||
typedef typename policies::evaluation<result_type, Policy>::type value_type;
|
||||
typedef typename lanczos::lanczos<value_type, Policy>::type evaluation_type;
|
||||
typedef typename policies::normalise<
|
||||
Policy,
|
||||
policies::promote_float<false>,
|
||||
policies::promote_double<false>,
|
||||
policies::discrete_quantile<>,
|
||||
policies::assert_undefined<> >::type forwarding_policy;
|
||||
|
||||
value_type result;
|
||||
if(N <= boost::math::max_factorial<value_type>::value)
|
||||
{
|
||||
//
|
||||
// If N is small enough then we can evaluate the PDF via the factorials
|
||||
// directly: table lookup of the factorials gives the best performance
|
||||
// of the methods available:
|
||||
//
|
||||
result = detail::hypergeometric_pdf_factorial_imp<value_type>(x, r, n, N, forwarding_policy());
|
||||
}
|
||||
else if(N <= boost::math::prime(boost::math::max_prime - 1))
|
||||
{
|
||||
//
|
||||
// If N is no larger than the largest prime number in our lookup table
|
||||
// (104729) then we can use prime factorisation to evaluate the PDF,
|
||||
// this is slow but accurate:
|
||||
//
|
||||
result = detail::hypergeometric_pdf_prime_imp<value_type>(x, r, n, N, forwarding_policy());
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// Catch all case - use the lanczos approximation - where available -
|
||||
// to evaluate the ratio of factorials. This is reasonably fast
|
||||
// (almost as quick as using logarithmic evaluation in terms of lgamma)
|
||||
// but only a few digits better in accuracy than using lgamma:
|
||||
//
|
||||
result = detail::hypergeometric_pdf_lanczos_imp(value_type(), x, r, n, N, evaluation_type(), forwarding_policy());
|
||||
}
|
||||
|
||||
if(result > 1)
|
||||
{
|
||||
result = 1;
|
||||
}
|
||||
if(result < 0)
|
||||
{
|
||||
result = 0;
|
||||
}
|
||||
|
||||
return policies::checked_narrowing_cast<result_type, forwarding_policy>(result, "boost::math::hypergeometric_pdf<%1%>(%1%,%1%,%1%,%1%)");
|
||||
}
|
||||
|
||||
}}} // namespaces
|
||||
|
||||
#endif
|
||||
|
@ -1,692 +0,0 @@
|
||||
// Copyright John Maddock 2007.
|
||||
// Copyright Paul A. Bristow 2007.
|
||||
|
||||
// Use, modification and distribution are subject to the
|
||||
// Boost Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_MATH_POLICY_ERROR_HANDLING_HPP
|
||||
#define BOOST_MATH_POLICY_ERROR_HANDLING_HPP
|
||||
|
||||
#include <stdexcept>
|
||||
#include <iomanip>
|
||||
#include <string>
|
||||
#include <cerrno>
|
||||
#include <complex>
|
||||
#include <boost/config/no_tr1/cmath.hpp>
|
||||
#include <stdexcept>
|
||||
#include <boost/math/tools/config.hpp>
|
||||
#include <boost/math/policies/policy.hpp>
|
||||
#include <boost/math/tools/precision.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
#ifdef BOOST_MSVC
|
||||
# pragma warning(push) // Quiet warnings in boost/format.hpp
|
||||
# pragma warning(disable: 4996) // _SCL_SECURE_NO_DEPRECATE
|
||||
# pragma warning(disable: 4512) // assignment operator could not be generated.
|
||||
// And warnings in error handling:
|
||||
# pragma warning(disable: 4702) // unreachable code
|
||||
// Note that this only occurs when the compiler can deduce code is unreachable,
|
||||
// for example when policy macros are used to ignore errors rather than throw.
|
||||
#endif
|
||||
#include <boost/format.hpp>
|
||||
#include <boost/type_index.hpp>
|
||||
|
||||
namespace boost{ namespace math{
|
||||
|
||||
class evaluation_error : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
evaluation_error(const std::string& s) : std::runtime_error(s){}
|
||||
};
|
||||
|
||||
class rounding_error : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
rounding_error(const std::string& s) : std::runtime_error(s){}
|
||||
};
|
||||
|
||||
namespace policies{
|
||||
//
|
||||
// Forward declarations of user error handlers,
|
||||
// it's up to the user to provide the definition of these:
|
||||
//
|
||||
template <class T>
|
||||
T user_domain_error(const char* function, const char* message, const T& val);
|
||||
template <class T>
|
||||
T user_pole_error(const char* function, const char* message, const T& val);
|
||||
template <class T>
|
||||
T user_overflow_error(const char* function, const char* message, const T& val);
|
||||
template <class T>
|
||||
T user_underflow_error(const char* function, const char* message, const T& val);
|
||||
template <class T>
|
||||
T user_denorm_error(const char* function, const char* message, const T& val);
|
||||
template <class T>
|
||||
T user_evaluation_error(const char* function, const char* message, const T& val);
|
||||
template <class T, class TargetType>
|
||||
T user_rounding_error(const char* function, const char* message, const T& val, const TargetType& t);
|
||||
template <class T>
|
||||
T user_indeterminate_result_error(const char* function, const char* message, const T& val);
|
||||
|
||||
namespace detail
|
||||
{
|
||||
//
|
||||
// Helper function to avoid binding rvalue to non-const-reference,
|
||||
// in other words a warning suppression mechansim:
|
||||
//
|
||||
template <class Formatter, class Group>
|
||||
inline std::string do_format(Formatter f, const Group& g)
|
||||
{
|
||||
return (f % g).str();
|
||||
}
|
||||
|
||||
template <class E, class T>
|
||||
void raise_error(const char* function, const char* message)
|
||||
{
|
||||
if(function == 0)
|
||||
function = "Unknown function operating on type %1%";
|
||||
if(message == 0)
|
||||
message = "Cause unknown";
|
||||
|
||||
std::string msg("Error in function ");
|
||||
msg += (boost::format(function) % type_id<T>().name_demangled()).str();
|
||||
msg += ": ";
|
||||
msg += message;
|
||||
|
||||
E e(msg);
|
||||
boost::throw_exception(e);
|
||||
}
|
||||
|
||||
template <class E, class T>
|
||||
void raise_error(const char* function, const char* message, const T& val)
|
||||
{
|
||||
if(function == 0)
|
||||
function = "Unknown function operating on type %1%";
|
||||
if(message == 0)
|
||||
message = "Cause unknown: error caused by bad argument with value %1%";
|
||||
|
||||
std::string msg("Error in function ");
|
||||
msg += (boost::format(function) % type_id<T>().name_demangled()).str();
|
||||
msg += ": ";
|
||||
msg += message;
|
||||
|
||||
int prec = 2 + (boost::math::policies::digits<T, boost::math::policies::policy<> >() * 30103UL) / 100000UL;
|
||||
msg = do_format(boost::format(msg), boost::io::group(std::setprecision(prec), val));
|
||||
|
||||
E e(msg);
|
||||
boost::throw_exception(e);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T raise_domain_error(
|
||||
const char* function,
|
||||
const char* message,
|
||||
const T& val,
|
||||
const ::boost::math::policies::domain_error< ::boost::math::policies::throw_on_error>&)
|
||||
{
|
||||
raise_error<std::domain_error, T>(function, message, val);
|
||||
// we never get here:
|
||||
return std::numeric_limits<T>::quiet_NaN();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T raise_domain_error(
|
||||
const char* ,
|
||||
const char* ,
|
||||
const T& ,
|
||||
const ::boost::math::policies::domain_error< ::boost::math::policies::ignore_error>&)
|
||||
{
|
||||
// This may or may not do the right thing, but the user asked for the error
|
||||
// to be ignored so here we go anyway:
|
||||
return std::numeric_limits<T>::quiet_NaN();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T raise_domain_error(
|
||||
const char* ,
|
||||
const char* ,
|
||||
const T& ,
|
||||
const ::boost::math::policies::domain_error< ::boost::math::policies::errno_on_error>&)
|
||||
{
|
||||
errno = EDOM;
|
||||
// This may or may not do the right thing, but the user asked for the error
|
||||
// to be silent so here we go anyway:
|
||||
return std::numeric_limits<T>::quiet_NaN();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T raise_domain_error(
|
||||
const char* function,
|
||||
const char* message,
|
||||
const T& val,
|
||||
const ::boost::math::policies::domain_error< ::boost::math::policies::user_error>&)
|
||||
{
|
||||
return user_domain_error(function, message, val);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T raise_pole_error(
|
||||
const char* function,
|
||||
const char* message,
|
||||
const T& val,
|
||||
const ::boost::math::policies::pole_error< ::boost::math::policies::throw_on_error>&)
|
||||
{
|
||||
return boost::math::policies::detail::raise_domain_error(function, message, val, ::boost::math::policies::domain_error< ::boost::math::policies::throw_on_error>());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T raise_pole_error(
|
||||
const char* function,
|
||||
const char* message,
|
||||
const T& val,
|
||||
const ::boost::math::policies::pole_error< ::boost::math::policies::ignore_error>&)
|
||||
{
|
||||
return ::boost::math::policies::detail::raise_domain_error(function, message, val, ::boost::math::policies::domain_error< ::boost::math::policies::ignore_error>());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T raise_pole_error(
|
||||
const char* function,
|
||||
const char* message,
|
||||
const T& val,
|
||||
const ::boost::math::policies::pole_error< ::boost::math::policies::errno_on_error>&)
|
||||
{
|
||||
return ::boost::math::policies::detail::raise_domain_error(function, message, val, ::boost::math::policies::domain_error< ::boost::math::policies::errno_on_error>());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T raise_pole_error(
|
||||
const char* function,
|
||||
const char* message,
|
||||
const T& val,
|
||||
const ::boost::math::policies::pole_error< ::boost::math::policies::user_error>&)
|
||||
{
|
||||
return user_pole_error(function, message, val);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T raise_overflow_error(
|
||||
const char* function,
|
||||
const char* message,
|
||||
const ::boost::math::policies::overflow_error< ::boost::math::policies::throw_on_error>&)
|
||||
{
|
||||
raise_error<std::overflow_error, T>(function, message ? message : "numeric overflow");
|
||||
// we never get here:
|
||||
return std::numeric_limits<T>::has_infinity ? std::numeric_limits<T>::infinity() : boost::math::tools::max_value<T>();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T raise_overflow_error(
|
||||
const char* ,
|
||||
const char* ,
|
||||
const ::boost::math::policies::overflow_error< ::boost::math::policies::ignore_error>&)
|
||||
{
|
||||
// This may or may not do the right thing, but the user asked for the error
|
||||
// to be ignored so here we go anyway:
|
||||
return std::numeric_limits<T>::has_infinity ? std::numeric_limits<T>::infinity() : boost::math::tools::max_value<T>();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T raise_overflow_error(
|
||||
const char* ,
|
||||
const char* ,
|
||||
const ::boost::math::policies::overflow_error< ::boost::math::policies::errno_on_error>&)
|
||||
{
|
||||
errno = ERANGE;
|
||||
// This may or may not do the right thing, but the user asked for the error
|
||||
// to be silent so here we go anyway:
|
||||
return std::numeric_limits<T>::has_infinity ? std::numeric_limits<T>::infinity() : boost::math::tools::max_value<T>();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T raise_overflow_error(
|
||||
const char* function,
|
||||
const char* message,
|
||||
const ::boost::math::policies::overflow_error< ::boost::math::policies::user_error>&)
|
||||
{
|
||||
return user_overflow_error(function, message, std::numeric_limits<T>::infinity());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T raise_underflow_error(
|
||||
const char* function,
|
||||
const char* message,
|
||||
const ::boost::math::policies::underflow_error< ::boost::math::policies::throw_on_error>&)
|
||||
{
|
||||
raise_error<std::underflow_error, T>(function, message ? message : "numeric underflow");
|
||||
// we never get here:
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T raise_underflow_error(
|
||||
const char* ,
|
||||
const char* ,
|
||||
const ::boost::math::policies::underflow_error< ::boost::math::policies::ignore_error>&)
|
||||
{
|
||||
// This may or may not do the right thing, but the user asked for the error
|
||||
// to be ignored so here we go anyway:
|
||||
return T(0);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T raise_underflow_error(
|
||||
const char* /* function */,
|
||||
const char* /* message */,
|
||||
const ::boost::math::policies::underflow_error< ::boost::math::policies::errno_on_error>&)
|
||||
{
|
||||
errno = ERANGE;
|
||||
// This may or may not do the right thing, but the user asked for the error
|
||||
// to be silent so here we go anyway:
|
||||
return T(0);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T raise_underflow_error(
|
||||
const char* function,
|
||||
const char* message,
|
||||
const ::boost::math::policies::underflow_error< ::boost::math::policies::user_error>&)
|
||||
{
|
||||
return user_underflow_error(function, message, T(0));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T raise_denorm_error(
|
||||
const char* function,
|
||||
const char* message,
|
||||
const T& /* val */,
|
||||
const ::boost::math::policies::denorm_error< ::boost::math::policies::throw_on_error>&)
|
||||
{
|
||||
raise_error<std::underflow_error, T>(function, message ? message : "denormalised result");
|
||||
// we never get here:
|
||||
return T(0);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T raise_denorm_error(
|
||||
const char* ,
|
||||
const char* ,
|
||||
const T& val,
|
||||
const ::boost::math::policies::denorm_error< ::boost::math::policies::ignore_error>&)
|
||||
{
|
||||
// This may or may not do the right thing, but the user asked for the error
|
||||
// to be ignored so here we go anyway:
|
||||
return val;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T raise_denorm_error(
|
||||
const char* ,
|
||||
const char* ,
|
||||
const T& val,
|
||||
const ::boost::math::policies::denorm_error< ::boost::math::policies::errno_on_error>&)
|
||||
{
|
||||
errno = ERANGE;
|
||||
// This may or may not do the right thing, but the user asked for the error
|
||||
// to be silent so here we go anyway:
|
||||
return val;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T raise_denorm_error(
|
||||
const char* function,
|
||||
const char* message,
|
||||
const T& val,
|
||||
const ::boost::math::policies::denorm_error< ::boost::math::policies::user_error>&)
|
||||
{
|
||||
return user_denorm_error(function, message, val);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T raise_evaluation_error(
|
||||
const char* function,
|
||||
const char* message,
|
||||
const T& val,
|
||||
const ::boost::math::policies::evaluation_error< ::boost::math::policies::throw_on_error>&)
|
||||
{
|
||||
raise_error<boost::math::evaluation_error, T>(function, message, val);
|
||||
// we never get here:
|
||||
return T(0);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T raise_evaluation_error(
|
||||
const char* ,
|
||||
const char* ,
|
||||
const T& val,
|
||||
const ::boost::math::policies::evaluation_error< ::boost::math::policies::ignore_error>&)
|
||||
{
|
||||
// This may or may not do the right thing, but the user asked for the error
|
||||
// to be ignored so here we go anyway:
|
||||
return val;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T raise_evaluation_error(
|
||||
const char* ,
|
||||
const char* ,
|
||||
const T& val,
|
||||
const ::boost::math::policies::evaluation_error< ::boost::math::policies::errno_on_error>&)
|
||||
{
|
||||
errno = EDOM;
|
||||
// This may or may not do the right thing, but the user asked for the error
|
||||
// to be silent so here we go anyway:
|
||||
return val;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T raise_evaluation_error(
|
||||
const char* function,
|
||||
const char* message,
|
||||
const T& val,
|
||||
const ::boost::math::policies::evaluation_error< ::boost::math::policies::user_error>&)
|
||||
{
|
||||
return user_evaluation_error(function, message, val);
|
||||
}
|
||||
|
||||
template <class T, class TargetType>
|
||||
inline T raise_rounding_error(
|
||||
const char* function,
|
||||
const char* message,
|
||||
const T& val,
|
||||
const TargetType&,
|
||||
const ::boost::math::policies::rounding_error< ::boost::math::policies::throw_on_error>&)
|
||||
{
|
||||
raise_error<boost::math::rounding_error, T>(function, message, val);
|
||||
// we never get here:
|
||||
return T(0);
|
||||
}
|
||||
|
||||
template <class T, class TargetType>
|
||||
inline T raise_rounding_error(
|
||||
const char* ,
|
||||
const char* ,
|
||||
const T& val,
|
||||
const TargetType&,
|
||||
const ::boost::math::policies::rounding_error< ::boost::math::policies::ignore_error>&)
|
||||
{
|
||||
// This may or may not do the right thing, but the user asked for the error
|
||||
// to be ignored so here we go anyway:
|
||||
return std::numeric_limits<T>::is_specialized ? (val > 0 ? (std::numeric_limits<T>::max)() : -(std::numeric_limits<T>::max)()): val;
|
||||
}
|
||||
|
||||
template <class T, class TargetType>
|
||||
inline T raise_rounding_error(
|
||||
const char* ,
|
||||
const char* ,
|
||||
const T& val,
|
||||
const TargetType&,
|
||||
const ::boost::math::policies::rounding_error< ::boost::math::policies::errno_on_error>&)
|
||||
{
|
||||
errno = ERANGE;
|
||||
// This may or may not do the right thing, but the user asked for the error
|
||||
// to be silent so here we go anyway:
|
||||
return std::numeric_limits<T>::is_specialized ? (val > 0 ? (std::numeric_limits<T>::max)() : -(std::numeric_limits<T>::max)()): val;
|
||||
}
|
||||
|
||||
template <class T, class TargetType>
|
||||
inline T raise_rounding_error(
|
||||
const char* function,
|
||||
const char* message,
|
||||
const T& val,
|
||||
const TargetType& t,
|
||||
const ::boost::math::policies::rounding_error< ::boost::math::policies::user_error>&)
|
||||
{
|
||||
return user_rounding_error(function, message, val, t);
|
||||
}
|
||||
|
||||
template <class T, class R>
|
||||
inline T raise_indeterminate_result_error(
|
||||
const char* function,
|
||||
const char* message,
|
||||
const T& val,
|
||||
const R& ,
|
||||
const ::boost::math::policies::indeterminate_result_error< ::boost::math::policies::throw_on_error>&)
|
||||
{
|
||||
raise_error<std::domain_error, T>(function, message, val);
|
||||
// we never get here:
|
||||
return std::numeric_limits<T>::quiet_NaN();
|
||||
}
|
||||
|
||||
template <class T, class R>
|
||||
inline T raise_indeterminate_result_error(
|
||||
const char* ,
|
||||
const char* ,
|
||||
const T& ,
|
||||
const R& result,
|
||||
const ::boost::math::policies::indeterminate_result_error< ::boost::math::policies::ignore_error>&)
|
||||
{
|
||||
// This may or may not do the right thing, but the user asked for the error
|
||||
// to be ignored so here we go anyway:
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class T, class R>
|
||||
inline T raise_indeterminate_result_error(
|
||||
const char* ,
|
||||
const char* ,
|
||||
const T& ,
|
||||
const R& result,
|
||||
const ::boost::math::policies::indeterminate_result_error< ::boost::math::policies::errno_on_error>&)
|
||||
{
|
||||
errno = EDOM;
|
||||
// This may or may not do the right thing, but the user asked for the error
|
||||
// to be silent so here we go anyway:
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class T, class R>
|
||||
inline T raise_indeterminate_result_error(
|
||||
const char* function,
|
||||
const char* message,
|
||||
const T& val,
|
||||
const R& ,
|
||||
const ::boost::math::policies::indeterminate_result_error< ::boost::math::policies::user_error>&)
|
||||
{
|
||||
return user_indeterminate_result_error(function, message, val);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class T, class Policy>
|
||||
inline T raise_domain_error(const char* function, const char* message, const T& val, const Policy&)
|
||||
{
|
||||
typedef typename Policy::domain_error_type policy_type;
|
||||
return detail::raise_domain_error(
|
||||
function, message ? message : "Domain Error evaluating function at %1%",
|
||||
val, policy_type());
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline T raise_pole_error(const char* function, const char* message, const T& val, const Policy&)
|
||||
{
|
||||
typedef typename Policy::pole_error_type policy_type;
|
||||
return detail::raise_pole_error(
|
||||
function, message ? message : "Evaluation of function at pole %1%",
|
||||
val, policy_type());
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline T raise_overflow_error(const char* function, const char* message, const Policy&)
|
||||
{
|
||||
typedef typename Policy::overflow_error_type policy_type;
|
||||
return detail::raise_overflow_error<T>(
|
||||
function, message ? message : "Overflow Error",
|
||||
policy_type());
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline T raise_underflow_error(const char* function, const char* message, const Policy&)
|
||||
{
|
||||
typedef typename Policy::underflow_error_type policy_type;
|
||||
return detail::raise_underflow_error<T>(
|
||||
function, message ? message : "Underflow Error",
|
||||
policy_type());
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline T raise_denorm_error(const char* function, const char* message, const T& val, const Policy&)
|
||||
{
|
||||
typedef typename Policy::denorm_error_type policy_type;
|
||||
return detail::raise_denorm_error<T>(
|
||||
function, message ? message : "Denorm Error",
|
||||
val,
|
||||
policy_type());
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline T raise_evaluation_error(const char* function, const char* message, const T& val, const Policy&)
|
||||
{
|
||||
typedef typename Policy::evaluation_error_type policy_type;
|
||||
return detail::raise_evaluation_error(
|
||||
function, message ? message : "Internal Evaluation Error, best value so far was %1%",
|
||||
val, policy_type());
|
||||
}
|
||||
|
||||
template <class T, class TargetType, class Policy>
|
||||
inline T raise_rounding_error(const char* function, const char* message, const T& val, const TargetType& t, const Policy&)
|
||||
{
|
||||
typedef typename Policy::rounding_error_type policy_type;
|
||||
return detail::raise_rounding_error(
|
||||
function, message ? message : "Value %1% can not be represented in the target integer type.",
|
||||
val, t, policy_type());
|
||||
}
|
||||
|
||||
template <class T, class R, class Policy>
|
||||
inline T raise_indeterminate_result_error(const char* function, const char* message, const T& val, const R& result, const Policy&)
|
||||
{
|
||||
typedef typename Policy::indeterminate_result_error_type policy_type;
|
||||
return detail::raise_indeterminate_result_error(
|
||||
function, message ? message : "Indeterminate result with value %1%",
|
||||
val, result, policy_type());
|
||||
}
|
||||
|
||||
//
|
||||
// checked_narrowing_cast:
|
||||
//
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template <class R, class T, class Policy>
|
||||
inline bool check_overflow(T val, R* result, const char* function, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
if(fabs(val) > tools::max_value<R>())
|
||||
{
|
||||
*result = static_cast<R>(boost::math::policies::detail::raise_overflow_error<R>(function, 0, pol));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
template <class R, class T, class Policy>
|
||||
inline bool check_overflow(std::complex<T> val, R* result, const char* function, const Policy& pol)
|
||||
{
|
||||
typedef typename R::value_type r_type;
|
||||
r_type re, im;
|
||||
bool r = check_overflow<r_type>(val.real(), &re, function, pol) || check_overflow<r_type>(val.imag(), &im, function, pol);
|
||||
*result = R(re, im);
|
||||
return r;
|
||||
}
|
||||
template <class R, class T, class Policy>
|
||||
inline bool check_underflow(T val, R* result, const char* function, const Policy& pol)
|
||||
{
|
||||
if((val != 0) && (static_cast<R>(val) == 0))
|
||||
{
|
||||
*result = static_cast<R>(boost::math::policies::detail::raise_underflow_error<R>(function, 0, pol));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
template <class R, class T, class Policy>
|
||||
inline bool check_underflow(std::complex<T> val, R* result, const char* function, const Policy& pol)
|
||||
{
|
||||
typedef typename R::value_type r_type;
|
||||
r_type re, im;
|
||||
bool r = check_underflow<r_type>(val.real(), &re, function, pol) || check_underflow<r_type>(val.imag(), &im, function, pol);
|
||||
*result = R(re, im);
|
||||
return r;
|
||||
}
|
||||
template <class R, class T, class Policy>
|
||||
inline bool check_denorm(T val, R* result, const char* function, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
if((fabs(val) < static_cast<T>(tools::min_value<R>())) && (static_cast<R>(val) != 0))
|
||||
{
|
||||
*result = static_cast<R>(boost::math::policies::detail::raise_denorm_error<R>(function, 0, static_cast<R>(val), pol));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
template <class R, class T, class Policy>
|
||||
inline bool check_denorm(std::complex<T> val, R* result, const char* function, const Policy& pol)
|
||||
{
|
||||
typedef typename R::value_type r_type;
|
||||
r_type re, im;
|
||||
bool r = check_denorm<r_type>(val.real(), &re, function, pol) || check_denorm<r_type>(val.imag(), &im, function, pol);
|
||||
*result = R(re, im);
|
||||
return r;
|
||||
}
|
||||
|
||||
// Default instantiations with ignore_error policy.
|
||||
template <class R, class T>
|
||||
inline bool check_overflow(T /* val */, R* /* result */, const char* /* function */, const overflow_error<ignore_error>&){ return false; }
|
||||
template <class R, class T>
|
||||
inline bool check_overflow(std::complex<T> /* val */, R* /* result */, const char* /* function */, const overflow_error<ignore_error>&){ return false; }
|
||||
template <class R, class T>
|
||||
inline bool check_underflow(T /* val */, R* /* result */, const char* /* function */, const underflow_error<ignore_error>&){ return false; }
|
||||
template <class R, class T>
|
||||
inline bool check_underflow(std::complex<T> /* val */, R* /* result */, const char* /* function */, const underflow_error<ignore_error>&){ return false; }
|
||||
template <class R, class T>
|
||||
inline bool check_denorm(T /* val */, R* /* result*/, const char* /* function */, const denorm_error<ignore_error>&){ return false; }
|
||||
template <class R, class T>
|
||||
inline bool check_denorm(std::complex<T> /* val */, R* /* result*/, const char* /* function */, const denorm_error<ignore_error>&){ return false; }
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class R, class Policy, class T>
|
||||
inline R checked_narrowing_cast(T val, const char* function)
|
||||
{
|
||||
typedef typename Policy::overflow_error_type overflow_type;
|
||||
typedef typename Policy::underflow_error_type underflow_type;
|
||||
typedef typename Policy::denorm_error_type denorm_type;
|
||||
//
|
||||
// Most of what follows will evaluate to a no-op:
|
||||
//
|
||||
R result = 0;
|
||||
if(detail::check_overflow<R>(val, &result, function, overflow_type()))
|
||||
return result;
|
||||
if(detail::check_underflow<R>(val, &result, function, underflow_type()))
|
||||
return result;
|
||||
if(detail::check_denorm<R>(val, &result, function, denorm_type()))
|
||||
return result;
|
||||
|
||||
return static_cast<R>(val);
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline void check_series_iterations(const char* function, boost::uintmax_t max_iter, const Policy& pol)
|
||||
{
|
||||
if(max_iter >= policies::get_max_series_iterations<Policy>())
|
||||
raise_evaluation_error<T>(
|
||||
function,
|
||||
"Series evaluation exceeded %1% iterations, giving up now.", static_cast<T>(static_cast<double>(max_iter)), pol);
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
inline void check_root_iterations(const char* function, boost::uintmax_t max_iter, const Policy& pol)
|
||||
{
|
||||
if(max_iter >= policies::get_max_root_iterations<Policy>())
|
||||
raise_evaluation_error<T>(
|
||||
function,
|
||||
"Root finding evaluation exceeded %1% iterations, giving up now.", static_cast<T>(static_cast<double>(max_iter)), pol);
|
||||
}
|
||||
|
||||
} //namespace policies
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
}} // namespaces boost/math
|
||||
|
||||
#endif // BOOST_MATH_POLICY_ERROR_HANDLING_HPP
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,69 +0,0 @@
|
||||
// Copyright 2008 Christophe Henry
|
||||
// henry UNDERSCORE christophe AT hotmail DOT com
|
||||
// This is an extended version of the state machine available in the boost::mpl library
|
||||
// Distributed under the same license as the original.
|
||||
// Copyright for the original version:
|
||||
// Copyright 2005 David Abrahams and Aleksey Gurtovoy. Distributed
|
||||
// under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_MSM_BACK_TOOLS_H
|
||||
#define BOOST_MSM_BACK_TOOLS_H
|
||||
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <boost/msm/back/common_types.hpp>
|
||||
#include <boost/msm/back/metafunctions.hpp>
|
||||
#include <boost/type_index.hpp>
|
||||
|
||||
namespace boost { namespace msm { namespace back
|
||||
{
|
||||
|
||||
// fills the array passed in with the state names in the correct order
|
||||
// the array must be big enough. To know the needed size, use mpl::size
|
||||
// on fsm::generate_state_set
|
||||
template <class stt>
|
||||
struct fill_state_names
|
||||
{
|
||||
fill_state_names(char const** names):m_names(names){}
|
||||
template <class StateType>
|
||||
void operator()(boost::msm::wrap<StateType> const&)
|
||||
{
|
||||
m_names[get_state_id<stt,StateType>::value]= type_id<StateType>().name_demangled();
|
||||
}
|
||||
private:
|
||||
char const** m_names;
|
||||
};
|
||||
|
||||
// fills the typeid-generated name of the given state in the string passed as argument
|
||||
template <class stt>
|
||||
struct get_state_name
|
||||
{
|
||||
get_state_name(std::string& name_to_fill, int state_id):m_name(name_to_fill),m_state_id(state_id){}
|
||||
template <class StateType>
|
||||
void operator()(boost::msm::wrap<StateType> const&)
|
||||
{
|
||||
if (get_state_id<stt,StateType>::value == m_state_id)
|
||||
{
|
||||
m_name = type_id<StateType>().name_demangled();
|
||||
}
|
||||
}
|
||||
private:
|
||||
std::string& m_name;
|
||||
int m_state_id;
|
||||
};
|
||||
|
||||
// displays the typeid of the given Type
|
||||
struct display_type
|
||||
{
|
||||
template <class Type>
|
||||
void operator()(boost::msm::wrap<Type> const&)
|
||||
{
|
||||
std::cout << type_id<Type>().name_demangled() << std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
} } }//boost::msm::back
|
||||
#endif //BOOST_MSM_BACK_TOOLS_H
|
@ -1,345 +0,0 @@
|
||||
#ifndef DYNAMIC_PROPERTY_MAP_RG09302004_HPP
|
||||
#define DYNAMIC_PROPERTY_MAP_RG09302004_HPP
|
||||
|
||||
// Copyright 2004-5 The Trustees of Indiana University.
|
||||
|
||||
// Use, modification and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// dynamic_property_map.hpp -
|
||||
// Support for runtime-polymorphic property maps. This header is factored
|
||||
// out of Doug Gregor's routines for reading GraphML files for use in reading
|
||||
// GraphViz graph files.
|
||||
|
||||
// Authors: Doug Gregor
|
||||
// Ronald Garcia
|
||||
//
|
||||
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <boost/property_map/property_map.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/any.hpp>
|
||||
#include <boost/function/function3.hpp>
|
||||
#include <boost/type_traits/is_convertible.hpp>
|
||||
#include <typeinfo>
|
||||
#include <boost/mpl/bool.hpp>
|
||||
#include <stdexcept>
|
||||
#include <sstream>
|
||||
#include <map>
|
||||
#include <boost/type.hpp>
|
||||
#include <boost/smart_ptr.hpp>
|
||||
#include <boost/type_index.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace detail {
|
||||
|
||||
// read_value -
|
||||
// A wrapper around lexical_cast, which does not behave as
|
||||
// desired for std::string types.
|
||||
template<typename Value>
|
||||
inline Value read_value(const std::string& value)
|
||||
{ return boost::lexical_cast<Value>(value); }
|
||||
|
||||
template<>
|
||||
inline std::string read_value<std::string>(const std::string& value)
|
||||
{ return value; }
|
||||
|
||||
}
|
||||
|
||||
|
||||
// dynamic_property_map -
|
||||
// This interface supports polymorphic manipulation of property maps.
|
||||
class dynamic_property_map
|
||||
{
|
||||
public:
|
||||
virtual ~dynamic_property_map() { }
|
||||
|
||||
virtual boost::any get(const any& key) = 0;
|
||||
virtual std::string get_string(const any& key) = 0;
|
||||
virtual void put(const any& key, const any& value) = 0;
|
||||
virtual type_index key() const = 0;
|
||||
virtual type_index value() const = 0;
|
||||
};
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Property map exceptions
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct dynamic_property_exception : public std::exception {
|
||||
virtual ~dynamic_property_exception() throw() {}
|
||||
virtual const char* what() const throw() = 0;
|
||||
};
|
||||
|
||||
struct property_not_found : public dynamic_property_exception {
|
||||
std::string property;
|
||||
mutable std::string statement;
|
||||
property_not_found(const std::string& property) : property(property) {}
|
||||
virtual ~property_not_found() throw() {}
|
||||
|
||||
const char* what() const throw() {
|
||||
if(statement.empty())
|
||||
statement =
|
||||
std::string("Property not found: ") + property + ".";
|
||||
|
||||
return statement.c_str();
|
||||
}
|
||||
};
|
||||
|
||||
struct dynamic_get_failure : public dynamic_property_exception {
|
||||
std::string property;
|
||||
mutable std::string statement;
|
||||
dynamic_get_failure(const std::string& property) : property(property) {}
|
||||
virtual ~dynamic_get_failure() throw() {}
|
||||
|
||||
const char* what() const throw() {
|
||||
if(statement.empty())
|
||||
statement =
|
||||
std::string(
|
||||
"dynamic property get cannot retrieve value for property: ")
|
||||
+ property + ".";
|
||||
|
||||
return statement.c_str();
|
||||
}
|
||||
};
|
||||
|
||||
struct dynamic_const_put_error : public dynamic_property_exception {
|
||||
virtual ~dynamic_const_put_error() throw() {}
|
||||
|
||||
const char* what() const throw() {
|
||||
return "Attempt to put a value into a const property map: ";
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
namespace detail {
|
||||
|
||||
// Trying to work around VC++ problem that seems to relate to having too many
|
||||
// functions named "get"
|
||||
template <typename PMap, typename Key>
|
||||
typename boost::property_traits<PMap>::reference
|
||||
get_wrapper_xxx(const PMap& pmap, const Key& key) {
|
||||
using boost::get;
|
||||
return get(pmap, key);
|
||||
}
|
||||
|
||||
//
|
||||
// dynamic_property_map_adaptor -
|
||||
// property-map adaptor to support runtime polymorphism.
|
||||
template<typename PropertyMap>
|
||||
class dynamic_property_map_adaptor : public dynamic_property_map
|
||||
{
|
||||
typedef typename property_traits<PropertyMap>::key_type key_type;
|
||||
typedef typename property_traits<PropertyMap>::value_type value_type;
|
||||
typedef typename property_traits<PropertyMap>::category category;
|
||||
|
||||
// do_put - overloaded dispatches from the put() member function.
|
||||
// Attempts to "put" to a property map that does not model
|
||||
// WritablePropertyMap result in a runtime exception.
|
||||
|
||||
// in_value must either hold an object of value_type or a string that
|
||||
// can be converted to value_type via iostreams.
|
||||
void do_put(const any& in_key, const any& in_value, mpl::bool_<true>)
|
||||
{
|
||||
using boost::put;
|
||||
|
||||
key_type key = any_cast<key_type>(in_key);
|
||||
if (in_value.type() == type_id<value_type>()) {
|
||||
put(property_map_, key, any_cast<value_type>(in_value));
|
||||
} else {
|
||||
// if in_value is an empty string, put a default constructed value_type.
|
||||
std::string v = any_cast<std::string>(in_value);
|
||||
if (v.empty()) {
|
||||
put(property_map_, key, value_type());
|
||||
} else {
|
||||
put(property_map_, key, detail::read_value<value_type>(v));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void do_put(const any&, const any&, mpl::bool_<false>)
|
||||
{
|
||||
BOOST_THROW_EXCEPTION(dynamic_const_put_error());
|
||||
}
|
||||
|
||||
public:
|
||||
explicit dynamic_property_map_adaptor(const PropertyMap& property_map_)
|
||||
: property_map_(property_map_) { }
|
||||
|
||||
virtual boost::any get(const any& key)
|
||||
{
|
||||
return get_wrapper_xxx(property_map_, any_cast<key_type>(key));
|
||||
}
|
||||
|
||||
virtual std::string get_string(const any& key)
|
||||
{
|
||||
std::ostringstream out;
|
||||
out << get_wrapper_xxx(property_map_, any_cast<key_type>(key));
|
||||
return out.str();
|
||||
}
|
||||
|
||||
virtual void put(const any& in_key, const any& in_value)
|
||||
{
|
||||
do_put(in_key, in_value,
|
||||
mpl::bool_<(is_convertible<category*,
|
||||
writable_property_map_tag*>::value)>());
|
||||
}
|
||||
|
||||
virtual type_index key() const { return type_id<key_type>(); }
|
||||
virtual type_index value() const { return type_id<value_type>(); }
|
||||
|
||||
PropertyMap& base() { return property_map_; }
|
||||
const PropertyMap& base() const { return property_map_; }
|
||||
|
||||
private:
|
||||
PropertyMap property_map_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
//
|
||||
// dynamic_properties -
|
||||
// container for dynamic property maps
|
||||
//
|
||||
struct dynamic_properties
|
||||
{
|
||||
typedef std::multimap<std::string, boost::shared_ptr<dynamic_property_map> >
|
||||
property_maps_type;
|
||||
typedef boost::function3<boost::shared_ptr<dynamic_property_map>,
|
||||
const std::string&,
|
||||
const boost::any&,
|
||||
const boost::any&> generate_fn_type;
|
||||
public:
|
||||
|
||||
typedef property_maps_type::iterator iterator;
|
||||
typedef property_maps_type::const_iterator const_iterator;
|
||||
|
||||
dynamic_properties() : generate_fn() { }
|
||||
dynamic_properties(const generate_fn_type& g) : generate_fn(g) {}
|
||||
|
||||
~dynamic_properties() {}
|
||||
|
||||
template<typename PropertyMap>
|
||||
dynamic_properties&
|
||||
property(const std::string& name, PropertyMap property_map_)
|
||||
{
|
||||
boost::shared_ptr<dynamic_property_map> pm(
|
||||
boost::make_shared<detail::dynamic_property_map_adaptor<PropertyMap> >(property_map_));
|
||||
property_maps.insert(property_maps_type::value_type(name, pm));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
iterator begin() { return property_maps.begin(); }
|
||||
const_iterator begin() const { return property_maps.begin(); }
|
||||
iterator end() { return property_maps.end(); }
|
||||
const_iterator end() const { return property_maps.end(); }
|
||||
|
||||
iterator lower_bound(const std::string& name)
|
||||
{ return property_maps.lower_bound(name); }
|
||||
|
||||
const_iterator lower_bound(const std::string& name) const
|
||||
{ return property_maps.lower_bound(name); }
|
||||
|
||||
void
|
||||
insert(const std::string& name, boost::shared_ptr<dynamic_property_map> pm)
|
||||
{
|
||||
property_maps.insert(property_maps_type::value_type(name, pm));
|
||||
}
|
||||
|
||||
template<typename Key, typename Value>
|
||||
boost::shared_ptr<dynamic_property_map>
|
||||
generate(const std::string& name, const Key& key, const Value& value)
|
||||
{
|
||||
if(!generate_fn) {
|
||||
BOOST_THROW_EXCEPTION(property_not_found(name));
|
||||
} else {
|
||||
return generate_fn(name,key,value);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
property_maps_type property_maps;
|
||||
generate_fn_type generate_fn;
|
||||
};
|
||||
|
||||
template<typename Key, typename Value>
|
||||
bool
|
||||
put(const std::string& name, dynamic_properties& dp, const Key& key,
|
||||
const Value& value)
|
||||
{
|
||||
for (dynamic_properties::iterator i = dp.lower_bound(name);
|
||||
i != dp.end() && i->first == name; ++i) {
|
||||
if (i->second->key() == type_id<key>()) {
|
||||
i->second->put(key, value);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
boost::shared_ptr<dynamic_property_map> new_map = dp.generate(name, key, value);
|
||||
if (new_map.get()) {
|
||||
new_map->put(key, value);
|
||||
dp.insert(name, new_map);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef BOOST_NO_EXPLICIT_FUNCTION_TEMPLATE_ARGUMENTS
|
||||
template<typename Value, typename Key>
|
||||
Value
|
||||
get(const std::string& name, const dynamic_properties& dp, const Key& key)
|
||||
{
|
||||
for (dynamic_properties::const_iterator i = dp.lower_bound(name);
|
||||
i != dp.end() && i->first == name; ++i) {
|
||||
if (i->second->key() == type_id<key>())
|
||||
return any_cast<Value>(i->second->get(key));
|
||||
}
|
||||
|
||||
BOOST_THROW_EXCEPTION(dynamic_get_failure(name));
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename Value, typename Key>
|
||||
Value
|
||||
get(const std::string& name, const dynamic_properties& dp, const Key& key, type<Value>)
|
||||
{
|
||||
for (dynamic_properties::const_iterator i = dp.lower_bound(name);
|
||||
i != dp.end() && i->first == name; ++i) {
|
||||
if (i->second->key() == type_id<key>())
|
||||
return any_cast<Value>(i->second->get(key));
|
||||
}
|
||||
|
||||
BOOST_THROW_EXCEPTION(dynamic_get_failure(name));
|
||||
}
|
||||
|
||||
template<typename Key>
|
||||
std::string
|
||||
get(const std::string& name, const dynamic_properties& dp, const Key& key)
|
||||
{
|
||||
for (dynamic_properties::const_iterator i = dp.lower_bound(name);
|
||||
i != dp.end() && i->first == name; ++i) {
|
||||
if (i->second->key() == type_id<key>())
|
||||
return i->second->get_string(key);
|
||||
}
|
||||
|
||||
BOOST_THROW_EXCEPTION(dynamic_get_failure(name));
|
||||
}
|
||||
|
||||
// The easy way to ignore properties.
|
||||
inline
|
||||
boost::shared_ptr<boost::dynamic_property_map>
|
||||
ignore_other_properties(const std::string&,
|
||||
const boost::any&,
|
||||
const boost::any&) {
|
||||
return boost::shared_ptr<boost::dynamic_property_map>();
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // DYNAMIC_PROPERTY_MAP_RG09302004_HPP
|
80
patched/property_map/dynamic_property_map.patch
Normal file
80
patched/property_map/dynamic_property_map.patch
Normal file
@ -0,0 +1,80 @@
|
||||
Index: .
|
||||
===================================================================
|
||||
--- . (revision 86520)
|
||||
+++ . (working copy)
|
||||
@@ -24,7 +24,7 @@
|
||||
#include <boost/any.hpp>
|
||||
#include <boost/function/function3.hpp>
|
||||
#include <boost/type_traits/is_convertible.hpp>
|
||||
-#include <typeinfo>
|
||||
+#include <boost/type_index/type_info.hpp>
|
||||
#include <boost/mpl/bool.hpp>
|
||||
#include <stdexcept>
|
||||
#include <sstream>
|
||||
@@ -60,8 +60,8 @@
|
||||
virtual boost::any get(const any& key) = 0;
|
||||
virtual std::string get_string(const any& key) = 0;
|
||||
virtual void put(const any& key, const any& value) = 0;
|
||||
- virtual const std::type_info& key() const = 0;
|
||||
- virtual const std::type_info& value() const = 0;
|
||||
+ virtual const boost::type_info& key() const = 0;
|
||||
+ virtual const boost::type_info& value() const = 0;
|
||||
};
|
||||
|
||||
|
||||
@@ -147,7 +147,7 @@
|
||||
using boost::put;
|
||||
|
||||
key_type key = any_cast<key_type>(in_key);
|
||||
- if (in_value.type() == typeid(value_type)) {
|
||||
+ if (in_value.type() == boost::type_id<value_type>()) {
|
||||
put(property_map_, key, any_cast<value_type>(in_value));
|
||||
} else {
|
||||
// if in_value is an empty string, put a default constructed value_type.
|
||||
@@ -188,8 +188,8 @@
|
||||
writable_property_map_tag*>::value)>());
|
||||
}
|
||||
|
||||
- virtual const std::type_info& key() const { return typeid(key_type); }
|
||||
- virtual const std::type_info& value() const { return typeid(value_type); }
|
||||
+ virtual const boost::type_info& key() const { return boost::type_id<key_type>(); }
|
||||
+ virtual const boost::type_info& value() const { return boost::type_id<value_type>(); }
|
||||
|
||||
PropertyMap& base() { return property_map_; }
|
||||
const PropertyMap& base() const { return property_map_; }
|
||||
@@ -283,7 +283,7 @@
|
||||
{
|
||||
for (dynamic_properties::iterator i = dp.lower_bound(name);
|
||||
i != dp.end() && i->first == name; ++i) {
|
||||
- if (i->second->key() == typeid(key)) {
|
||||
+ if (i->second->key() == boost::type_id<Key>()) {
|
||||
i->second->put(key, value);
|
||||
return true;
|
||||
}
|
||||
@@ -305,7 +305,7 @@
|
||||
{
|
||||
for (dynamic_properties::const_iterator i = dp.lower_bound(name);
|
||||
i != dp.end() && i->first == name; ++i) {
|
||||
- if (i->second->key() == typeid(key))
|
||||
+ if (i->second->key() == boost::type_id<Key>())
|
||||
return any_cast<Value>(i->second->get(key));
|
||||
}
|
||||
|
||||
@@ -318,7 +318,7 @@
|
||||
{
|
||||
for (dynamic_properties::const_iterator i = dp.lower_bound(name);
|
||||
i != dp.end() && i->first == name; ++i) {
|
||||
- if (i->second->key() == typeid(key))
|
||||
+ if (i->second->key() == boost::type_id<Key>())
|
||||
return any_cast<Value>(i->second->get(key));
|
||||
}
|
||||
|
||||
@@ -331,7 +331,7 @@
|
||||
{
|
||||
for (dynamic_properties::const_iterator i = dp.lower_bound(name);
|
||||
i != dp.end() && i->first == name; ++i) {
|
||||
- if (i->second->key() == typeid(key))
|
||||
+ if (i->second->key() == boost::type_id<Key>())
|
||||
return i->second->get_string(key);
|
||||
}
|
||||
|
@ -1,915 +0,0 @@
|
||||
// ----------------------------------------------------------------------------
|
||||
// Copyright (C) 2002-2006 Marcin Kalicinski
|
||||
// Copyright (C) 2009 Sebastian Redl
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// For more information, see www.boost.org
|
||||
// ----------------------------------------------------------------------------
|
||||
#ifndef BOOST_PROPERTY_TREE_DETAIL_PTREE_IMPLEMENTATION_HPP_INCLUDED
|
||||
#define BOOST_PROPERTY_TREE_DETAIL_PTREE_IMPLEMENTATION_HPP_INCLUDED
|
||||
|
||||
#include <boost/iterator/iterator_adaptor.hpp>
|
||||
#include <boost/iterator/reverse_iterator.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/type_index.hpp>
|
||||
#include <boost/utility/swap.hpp>
|
||||
#include <memory>
|
||||
|
||||
#if (defined(BOOST_MSVC) && \
|
||||
(_MSC_FULL_VER >= 160000000 && _MSC_FULL_VER < 170000000)) || \
|
||||
(defined(BOOST_INTEL_WIN) && \
|
||||
defined(BOOST_DINKUMWARE_STDLIB))
|
||||
#define BOOST_PROPERTY_TREE_PAIR_BUG
|
||||
#endif
|
||||
|
||||
namespace boost { namespace property_tree
|
||||
{
|
||||
template <class K, class D, class C>
|
||||
struct basic_ptree<K, D, C>::subs
|
||||
{
|
||||
struct by_name {};
|
||||
// The actual child container.
|
||||
#if defined(BOOST_PROPERTY_TREE_PAIR_BUG)
|
||||
// MSVC 10 has moved std::pair's members to a base
|
||||
// class. Unfortunately this does break the interface.
|
||||
BOOST_STATIC_CONSTANT(unsigned,
|
||||
first_offset = offsetof(value_type, first));
|
||||
#endif
|
||||
typedef multi_index_container<value_type,
|
||||
multi_index::indexed_by<
|
||||
multi_index::sequenced<>,
|
||||
multi_index::ordered_non_unique<multi_index::tag<by_name>,
|
||||
#if defined(BOOST_PROPERTY_TREE_PAIR_BUG)
|
||||
multi_index::member_offset<value_type, const key_type,
|
||||
first_offset>,
|
||||
#else
|
||||
multi_index::member<value_type, const key_type,
|
||||
&value_type::first>,
|
||||
#endif
|
||||
key_compare
|
||||
>
|
||||
>
|
||||
> base_container;
|
||||
|
||||
// The by-name lookup index.
|
||||
typedef typename base_container::template index<by_name>::type
|
||||
by_name_index;
|
||||
|
||||
// Access functions for getting to the children of a tree.
|
||||
static base_container& ch(self_type *s) {
|
||||
return *static_cast<base_container*>(s->m_children);
|
||||
}
|
||||
static const base_container& ch(const self_type *s) {
|
||||
return *static_cast<const base_container*>(s->m_children);
|
||||
}
|
||||
static by_name_index& assoc(self_type *s) {
|
||||
return ch(s).BOOST_NESTED_TEMPLATE get<by_name>();
|
||||
}
|
||||
static const by_name_index& assoc(const self_type *s) {
|
||||
return ch(s).BOOST_NESTED_TEMPLATE get<by_name>();
|
||||
}
|
||||
};
|
||||
template <class K, class D, class C>
|
||||
class basic_ptree<K, D, C>::iterator : public boost::iterator_adaptor<
|
||||
iterator, typename subs::base_container::iterator, value_type>
|
||||
{
|
||||
friend class boost::iterator_core_access;
|
||||
typedef boost::iterator_adaptor<
|
||||
iterator, typename subs::base_container::iterator, value_type>
|
||||
baset;
|
||||
public:
|
||||
typedef typename baset::reference reference;
|
||||
iterator() {}
|
||||
explicit iterator(typename iterator::base_type b)
|
||||
: iterator::iterator_adaptor_(b)
|
||||
{}
|
||||
reference dereference() const
|
||||
{
|
||||
// multi_index doesn't allow modification of its values, because
|
||||
// indexes could sort by anything, and modification screws that up.
|
||||
// However, we only sort by the key, and it's protected against
|
||||
// modification in the value_type, so this const_cast is safe.
|
||||
return const_cast<reference>(*this->base_reference());
|
||||
}
|
||||
};
|
||||
template <class K, class D, class C>
|
||||
class basic_ptree<K, D, C>::const_iterator : public boost::iterator_adaptor<
|
||||
const_iterator, typename subs::base_container::const_iterator>
|
||||
{
|
||||
public:
|
||||
const_iterator() {}
|
||||
explicit const_iterator(typename const_iterator::base_type b)
|
||||
: const_iterator::iterator_adaptor_(b)
|
||||
{}
|
||||
const_iterator(iterator b)
|
||||
: const_iterator::iterator_adaptor_(b.base())
|
||||
{}
|
||||
};
|
||||
template <class K, class D, class C>
|
||||
class basic_ptree<K, D, C>::reverse_iterator
|
||||
: public boost::reverse_iterator<iterator>
|
||||
{
|
||||
public:
|
||||
reverse_iterator() {}
|
||||
explicit reverse_iterator(iterator b)
|
||||
: boost::reverse_iterator<iterator>(b)
|
||||
{}
|
||||
};
|
||||
template <class K, class D, class C>
|
||||
class basic_ptree<K, D, C>::const_reverse_iterator
|
||||
: public boost::reverse_iterator<const_iterator>
|
||||
{
|
||||
public:
|
||||
const_reverse_iterator() {}
|
||||
explicit const_reverse_iterator(const_iterator b)
|
||||
: boost::reverse_iterator<const_iterator>(b)
|
||||
{}
|
||||
const_reverse_iterator(
|
||||
typename basic_ptree<K, D, C>::reverse_iterator b)
|
||||
: boost::reverse_iterator<const_iterator>(b)
|
||||
{}
|
||||
};
|
||||
template <class K, class D, class C>
|
||||
class basic_ptree<K, D, C>::assoc_iterator
|
||||
: public boost::iterator_adaptor<assoc_iterator,
|
||||
typename subs::by_name_index::iterator,
|
||||
value_type>
|
||||
{
|
||||
friend class boost::iterator_core_access;
|
||||
typedef boost::iterator_adaptor<assoc_iterator,
|
||||
typename subs::by_name_index::iterator,
|
||||
value_type>
|
||||
baset;
|
||||
public:
|
||||
typedef typename baset::reference reference;
|
||||
assoc_iterator() {}
|
||||
explicit assoc_iterator(typename assoc_iterator::base_type b)
|
||||
: assoc_iterator::iterator_adaptor_(b)
|
||||
{}
|
||||
reference dereference() const
|
||||
{
|
||||
return const_cast<reference>(*this->base_reference());
|
||||
}
|
||||
};
|
||||
template <class K, class D, class C>
|
||||
class basic_ptree<K, D, C>::const_assoc_iterator
|
||||
: public boost::iterator_adaptor<const_assoc_iterator,
|
||||
typename subs::by_name_index::const_iterator>
|
||||
{
|
||||
public:
|
||||
const_assoc_iterator() {}
|
||||
explicit const_assoc_iterator(
|
||||
typename const_assoc_iterator::base_type b)
|
||||
: const_assoc_iterator::iterator_adaptor_(b)
|
||||
{}
|
||||
const_assoc_iterator(assoc_iterator b)
|
||||
: const_assoc_iterator::iterator_adaptor_(b.base())
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
// Big five
|
||||
|
||||
// Perhaps the children collection could be created on-demand only, to
|
||||
// reduce heap traffic. But that's a lot more work to implement.
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
basic_ptree<K, D, C>::basic_ptree()
|
||||
: m_children(new typename subs::base_container)
|
||||
{
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
basic_ptree<K, D, C>::basic_ptree(const data_type &d)
|
||||
: m_data(d), m_children(new typename subs::base_container)
|
||||
{
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
basic_ptree<K, D, C>::basic_ptree(const basic_ptree<K, D, C> &rhs)
|
||||
: m_data(rhs.m_data),
|
||||
m_children(new typename subs::base_container(subs::ch(&rhs)))
|
||||
{
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
basic_ptree<K, D, C> &
|
||||
basic_ptree<K, D, C>::operator =(const basic_ptree<K, D, C> &rhs)
|
||||
{
|
||||
self_type(rhs).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
basic_ptree<K, D, C>::~basic_ptree()
|
||||
{
|
||||
delete &subs::ch(this);
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
void basic_ptree<K, D, C>::swap(basic_ptree<K, D, C> &rhs)
|
||||
{
|
||||
boost::swap(m_data, rhs.m_data);
|
||||
// Void pointers, no ADL necessary
|
||||
std::swap(m_children, rhs.m_children);
|
||||
}
|
||||
|
||||
// Container view
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::size_type
|
||||
basic_ptree<K, D, C>::size() const
|
||||
{
|
||||
return subs::ch(this).size();
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::size_type
|
||||
basic_ptree<K, D, C>::max_size() const
|
||||
{
|
||||
return subs::ch(this).max_size();
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
bool basic_ptree<K, D, C>::empty() const
|
||||
{
|
||||
return subs::ch(this).empty();
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::iterator
|
||||
basic_ptree<K, D, C>::begin()
|
||||
{
|
||||
return iterator(subs::ch(this).begin());
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::const_iterator
|
||||
basic_ptree<K, D, C>::begin() const
|
||||
{
|
||||
return const_iterator(subs::ch(this).begin());
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::iterator
|
||||
basic_ptree<K, D, C>::end()
|
||||
{
|
||||
return iterator(subs::ch(this).end());
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::const_iterator
|
||||
basic_ptree<K, D, C>::end() const
|
||||
{
|
||||
return const_iterator(subs::ch(this).end());
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::reverse_iterator
|
||||
basic_ptree<K, D, C>::rbegin()
|
||||
{
|
||||
return reverse_iterator(this->end());
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::const_reverse_iterator
|
||||
basic_ptree<K, D, C>::rbegin() const
|
||||
{
|
||||
return const_reverse_iterator(this->end());
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::reverse_iterator
|
||||
basic_ptree<K, D, C>::rend()
|
||||
{
|
||||
return reverse_iterator(this->begin());
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::const_reverse_iterator
|
||||
basic_ptree<K, D, C>::rend() const
|
||||
{
|
||||
return const_reverse_iterator(this->begin());
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::value_type &
|
||||
basic_ptree<K, D, C>::front()
|
||||
{
|
||||
return const_cast<value_type&>(subs::ch(this).front());
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
const typename basic_ptree<K, D, C>::value_type &
|
||||
basic_ptree<K, D, C>::front() const
|
||||
{
|
||||
return subs::ch(this).front();
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::value_type &
|
||||
basic_ptree<K, D, C>::back()
|
||||
{
|
||||
return const_cast<value_type&>(subs::ch(this).back());
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
const typename basic_ptree<K, D, C>::value_type &
|
||||
basic_ptree<K, D, C>::back() const
|
||||
{
|
||||
return subs::ch(this).back();
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::iterator
|
||||
basic_ptree<K, D, C>::insert(iterator where, const value_type &value)
|
||||
{
|
||||
return iterator(subs::ch(this).insert(where.base(), value).first);
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
template<class It> inline
|
||||
void basic_ptree<K, D, C>::insert(iterator where, It first, It last)
|
||||
{
|
||||
subs::ch(this).insert(where.base(), first, last);
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::iterator
|
||||
basic_ptree<K, D, C>::erase(iterator where)
|
||||
{
|
||||
return iterator(subs::ch(this).erase(where.base()));
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::iterator
|
||||
basic_ptree<K, D, C>::erase(iterator first, iterator last)
|
||||
{
|
||||
return iterator(subs::ch(this).erase(first.base(), last.base()));
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::iterator
|
||||
basic_ptree<K, D, C>::push_front(const value_type &value)
|
||||
{
|
||||
return iterator(subs::ch(this).push_front(value).first);
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::iterator
|
||||
basic_ptree<K, D, C>::push_back(const value_type &value)
|
||||
{
|
||||
return iterator(subs::ch(this).push_back(value).first);
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
void basic_ptree<K, D, C>::pop_front()
|
||||
{
|
||||
subs::ch(this).pop_front();
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
void basic_ptree<K, D, C>::pop_back()
|
||||
{
|
||||
subs::ch(this).pop_back();
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
void basic_ptree<K, D, C>::reverse()
|
||||
{
|
||||
subs::ch(this).reverse();
|
||||
}
|
||||
|
||||
namespace impl
|
||||
{
|
||||
struct by_first
|
||||
{
|
||||
template <typename P>
|
||||
bool operator ()(const P& lhs, const P& rhs) const {
|
||||
return lhs.first < rhs.first;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
void basic_ptree<K, D, C>::sort()
|
||||
{
|
||||
sort(impl::by_first());
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
template<class Compare> inline
|
||||
void basic_ptree<K, D, C>::sort(Compare comp)
|
||||
{
|
||||
subs::ch(this).sort(comp);
|
||||
}
|
||||
|
||||
// Equality
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
bool basic_ptree<K, D, C>::operator ==(
|
||||
const basic_ptree<K, D, C> &rhs) const
|
||||
{
|
||||
// The size test is cheap, so add it as an optimization
|
||||
return size() == rhs.size() && data() == rhs.data() &&
|
||||
subs::ch(this) == subs::ch(&rhs);
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
bool basic_ptree<K, D, C>::operator !=(
|
||||
const basic_ptree<K, D, C> &rhs) const
|
||||
{
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
// Associative view
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::assoc_iterator
|
||||
basic_ptree<K, D, C>::ordered_begin()
|
||||
{
|
||||
return assoc_iterator(subs::assoc(this).begin());
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::const_assoc_iterator
|
||||
basic_ptree<K, D, C>::ordered_begin() const
|
||||
{
|
||||
return const_assoc_iterator(subs::assoc(this).begin());
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::assoc_iterator
|
||||
basic_ptree<K, D, C>::not_found()
|
||||
{
|
||||
return assoc_iterator(subs::assoc(this).end());
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::const_assoc_iterator
|
||||
basic_ptree<K, D, C>::not_found() const
|
||||
{
|
||||
return const_assoc_iterator(subs::assoc(this).end());
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::assoc_iterator
|
||||
basic_ptree<K, D, C>::find(const key_type &key)
|
||||
{
|
||||
return assoc_iterator(subs::assoc(this).find(key));
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::const_assoc_iterator
|
||||
basic_ptree<K, D, C>::find(const key_type &key) const
|
||||
{
|
||||
return const_assoc_iterator(subs::assoc(this).find(key));
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
std::pair<
|
||||
typename basic_ptree<K, D, C>::assoc_iterator,
|
||||
typename basic_ptree<K, D, C>::assoc_iterator
|
||||
> basic_ptree<K, D, C>::equal_range(const key_type &key)
|
||||
{
|
||||
std::pair<typename subs::by_name_index::iterator,
|
||||
typename subs::by_name_index::iterator> r(
|
||||
subs::assoc(this).equal_range(key));
|
||||
return std::pair<assoc_iterator, assoc_iterator>(
|
||||
assoc_iterator(r.first), assoc_iterator(r.second));
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
std::pair<
|
||||
typename basic_ptree<K, D, C>::const_assoc_iterator,
|
||||
typename basic_ptree<K, D, C>::const_assoc_iterator
|
||||
> basic_ptree<K, D, C>::equal_range(const key_type &key) const
|
||||
{
|
||||
std::pair<typename subs::by_name_index::const_iterator,
|
||||
typename subs::by_name_index::const_iterator> r(
|
||||
subs::assoc(this).equal_range(key));
|
||||
return std::pair<const_assoc_iterator, const_assoc_iterator>(
|
||||
const_assoc_iterator(r.first), const_assoc_iterator(r.second));
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::size_type
|
||||
basic_ptree<K, D, C>::count(const key_type &key) const
|
||||
{
|
||||
return subs::assoc(this).count(key);
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::size_type
|
||||
basic_ptree<K, D, C>::erase(const key_type &key)
|
||||
{
|
||||
return subs::assoc(this).erase(key);
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::iterator
|
||||
basic_ptree<K, D, C>::to_iterator(assoc_iterator ai)
|
||||
{
|
||||
return iterator(subs::ch(this).
|
||||
BOOST_NESTED_TEMPLATE project<0>(ai.base()));
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::const_iterator
|
||||
basic_ptree<K, D, C>::to_iterator(const_assoc_iterator ai) const
|
||||
{
|
||||
return const_iterator(subs::ch(this).
|
||||
BOOST_NESTED_TEMPLATE project<0>(ai.base()));
|
||||
}
|
||||
|
||||
// Property tree view
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::data_type &
|
||||
basic_ptree<K, D, C>::data()
|
||||
{
|
||||
return m_data;
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
const typename basic_ptree<K, D, C>::data_type &
|
||||
basic_ptree<K, D, C>::data() const
|
||||
{
|
||||
return m_data;
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
void basic_ptree<K, D, C>::clear()
|
||||
{
|
||||
m_data = data_type();
|
||||
subs::ch(this).clear();
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
basic_ptree<K, D, C> &
|
||||
basic_ptree<K, D, C>::get_child(const path_type &path)
|
||||
{
|
||||
path_type p(path);
|
||||
self_type *n = walk_path(p);
|
||||
if (!n) {
|
||||
BOOST_PROPERTY_TREE_THROW(ptree_bad_path("No such node", path));
|
||||
}
|
||||
return *n;
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
const basic_ptree<K, D, C> &
|
||||
basic_ptree<K, D, C>::get_child(const path_type &path) const
|
||||
{
|
||||
return const_cast<self_type*>(this)->get_child(path);
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
basic_ptree<K, D, C> &
|
||||
basic_ptree<K, D, C>::get_child(const path_type &path,
|
||||
self_type &default_value)
|
||||
{
|
||||
path_type p(path);
|
||||
self_type *n = walk_path(p);
|
||||
return n ? *n : default_value;
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
const basic_ptree<K, D, C> &
|
||||
basic_ptree<K, D, C>::get_child(const path_type &path,
|
||||
const self_type &default_value) const
|
||||
{
|
||||
return const_cast<self_type*>(this)->get_child(path,
|
||||
const_cast<self_type&>(default_value));
|
||||
}
|
||||
|
||||
|
||||
template<class K, class D, class C>
|
||||
optional<basic_ptree<K, D, C> &>
|
||||
basic_ptree<K, D, C>::get_child_optional(const path_type &path)
|
||||
{
|
||||
path_type p(path);
|
||||
self_type *n = walk_path(p);
|
||||
if (!n) {
|
||||
return optional<self_type&>();
|
||||
}
|
||||
return *n;
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
optional<const basic_ptree<K, D, C> &>
|
||||
basic_ptree<K, D, C>::get_child_optional(const path_type &path) const
|
||||
{
|
||||
path_type p(path);
|
||||
self_type *n = walk_path(p);
|
||||
if (!n) {
|
||||
return optional<const self_type&>();
|
||||
}
|
||||
return *n;
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
basic_ptree<K, D, C> &
|
||||
basic_ptree<K, D, C>::put_child(const path_type &path,
|
||||
const self_type &value)
|
||||
{
|
||||
path_type p(path);
|
||||
self_type &parent = force_path(p);
|
||||
// Got the parent. Now get the correct child.
|
||||
key_type fragment = p.reduce();
|
||||
assoc_iterator el = parent.find(fragment);
|
||||
// If the new child exists, replace it.
|
||||
if(el != parent.not_found()) {
|
||||
return el->second = value;
|
||||
} else {
|
||||
return parent.push_back(value_type(fragment, value))->second;
|
||||
}
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
basic_ptree<K, D, C> &
|
||||
basic_ptree<K, D, C>::add_child(const path_type &path,
|
||||
const self_type &value)
|
||||
{
|
||||
path_type p(path);
|
||||
self_type &parent = force_path(p);
|
||||
// Got the parent.
|
||||
key_type fragment = p.reduce();
|
||||
return parent.push_back(value_type(fragment, value))->second;
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
template<class Type, class Translator>
|
||||
typename boost::enable_if<detail::is_translator<Translator>, Type>::type
|
||||
basic_ptree<K, D, C>::get_value(Translator tr) const
|
||||
{
|
||||
if(boost::optional<Type> o = get_value_optional<Type>(tr)) {
|
||||
return *o;
|
||||
}
|
||||
BOOST_PROPERTY_TREE_THROW(ptree_bad_data(
|
||||
std::string("conversion of data to type \"") +
|
||||
type_id<Type>().name_demangled() + "\" failed", data()));
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
template<class Type> inline
|
||||
Type basic_ptree<K, D, C>::get_value() const
|
||||
{
|
||||
return get_value<Type>(
|
||||
typename translator_between<data_type, Type>::type());
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
template<class Type, class Translator> inline
|
||||
Type basic_ptree<K, D, C>::get_value(const Type &default_value,
|
||||
Translator tr) const
|
||||
{
|
||||
return get_value_optional<Type>(tr).get_value_or(default_value);
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
template <class Ch, class Translator>
|
||||
typename boost::enable_if<
|
||||
detail::is_character<Ch>,
|
||||
std::basic_string<Ch>
|
||||
>::type
|
||||
basic_ptree<K, D, C>::get_value(const Ch *default_value, Translator tr)const
|
||||
{
|
||||
return get_value<std::basic_string<Ch>, Translator>(default_value, tr);
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
template<class Type> inline
|
||||
typename boost::disable_if<detail::is_translator<Type>, Type>::type
|
||||
basic_ptree<K, D, C>::get_value(const Type &default_value) const
|
||||
{
|
||||
return get_value(default_value,
|
||||
typename translator_between<data_type, Type>::type());
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
template <class Ch>
|
||||
typename boost::enable_if<
|
||||
detail::is_character<Ch>,
|
||||
std::basic_string<Ch>
|
||||
>::type
|
||||
basic_ptree<K, D, C>::get_value(const Ch *default_value) const
|
||||
{
|
||||
return get_value< std::basic_string<Ch> >(default_value);
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
template<class Type, class Translator> inline
|
||||
optional<Type> basic_ptree<K, D, C>::get_value_optional(
|
||||
Translator tr) const
|
||||
{
|
||||
return tr.get_value(data());
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
template<class Type> inline
|
||||
optional<Type> basic_ptree<K, D, C>::get_value_optional() const
|
||||
{
|
||||
return get_value_optional<Type>(
|
||||
typename translator_between<data_type, Type>::type());
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
template<class Type, class Translator> inline
|
||||
typename boost::enable_if<detail::is_translator<Translator>, Type>::type
|
||||
basic_ptree<K, D, C>::get(const path_type &path,
|
||||
Translator tr) const
|
||||
{
|
||||
return get_child(path).BOOST_NESTED_TEMPLATE get_value<Type>(tr);
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
template<class Type> inline
|
||||
Type basic_ptree<K, D, C>::get(const path_type &path) const
|
||||
{
|
||||
return get_child(path).BOOST_NESTED_TEMPLATE get_value<Type>();
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
template<class Type, class Translator> inline
|
||||
Type basic_ptree<K, D, C>::get(const path_type &path,
|
||||
const Type &default_value,
|
||||
Translator tr) const
|
||||
{
|
||||
return get_optional<Type>(path, tr).get_value_or(default_value);
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
template <class Ch, class Translator>
|
||||
typename boost::enable_if<
|
||||
detail::is_character<Ch>,
|
||||
std::basic_string<Ch>
|
||||
>::type
|
||||
basic_ptree<K, D, C>::get(
|
||||
const path_type &path, const Ch *default_value, Translator tr) const
|
||||
{
|
||||
return get<std::basic_string<Ch>, Translator>(path, default_value, tr);
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
template<class Type> inline
|
||||
typename boost::disable_if<detail::is_translator<Type>, Type>::type
|
||||
basic_ptree<K, D, C>::get(const path_type &path,
|
||||
const Type &default_value) const
|
||||
{
|
||||
return get_optional<Type>(path).get_value_or(default_value);
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
template <class Ch>
|
||||
typename boost::enable_if<
|
||||
detail::is_character<Ch>,
|
||||
std::basic_string<Ch>
|
||||
>::type
|
||||
basic_ptree<K, D, C>::get(
|
||||
const path_type &path, const Ch *default_value) const
|
||||
{
|
||||
return get< std::basic_string<Ch> >(path, default_value);
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
template<class Type, class Translator>
|
||||
optional<Type> basic_ptree<K, D, C>::get_optional(const path_type &path,
|
||||
Translator tr) const
|
||||
{
|
||||
if (optional<const self_type&> child = get_child_optional(path))
|
||||
return child.get().
|
||||
BOOST_NESTED_TEMPLATE get_value_optional<Type>(tr);
|
||||
else
|
||||
return optional<Type>();
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
template<class Type>
|
||||
optional<Type> basic_ptree<K, D, C>::get_optional(
|
||||
const path_type &path) const
|
||||
{
|
||||
if (optional<const self_type&> child = get_child_optional(path))
|
||||
return child.get().BOOST_NESTED_TEMPLATE get_value_optional<Type>();
|
||||
else
|
||||
return optional<Type>();
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
template<class Type, class Translator>
|
||||
void basic_ptree<K, D, C>::put_value(const Type &value, Translator tr)
|
||||
{
|
||||
if(optional<data_type> o = tr.put_value(value)) {
|
||||
data() = *o;
|
||||
} else {
|
||||
BOOST_PROPERTY_TREE_THROW(ptree_bad_data(
|
||||
std::string("conversion of type \"") + type_id<Type>().name_demangled() +
|
||||
"\" to data failed", boost::any()));
|
||||
}
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
template<class Type> inline
|
||||
void basic_ptree<K, D, C>::put_value(const Type &value)
|
||||
{
|
||||
put_value(value, typename translator_between<data_type, Type>::type());
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
template<class Type, typename Translator>
|
||||
basic_ptree<K, D, C> & basic_ptree<K, D, C>::put(
|
||||
const path_type &path, const Type &value, Translator tr)
|
||||
{
|
||||
if(optional<self_type &> child = get_child_optional(path)) {
|
||||
child.get().put_value(value, tr);
|
||||
return *child;
|
||||
} else {
|
||||
self_type &child2 = put_child(path, self_type());
|
||||
child2.put_value(value, tr);
|
||||
return child2;
|
||||
}
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
template<class Type> inline
|
||||
basic_ptree<K, D, C> & basic_ptree<K, D, C>::put(
|
||||
const path_type &path, const Type &value)
|
||||
{
|
||||
return put(path, value,
|
||||
typename translator_between<data_type, Type>::type());
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
template<class Type, typename Translator> inline
|
||||
basic_ptree<K, D, C> & basic_ptree<K, D, C>::add(
|
||||
const path_type &path, const Type &value, Translator tr)
|
||||
{
|
||||
self_type &child = add_child(path, self_type());
|
||||
child.put_value(value, tr);
|
||||
return child;
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
template<class Type> inline
|
||||
basic_ptree<K, D, C> & basic_ptree<K, D, C>::add(
|
||||
const path_type &path, const Type &value)
|
||||
{
|
||||
return add(path, value,
|
||||
typename translator_between<data_type, Type>::type());
|
||||
}
|
||||
|
||||
|
||||
template<class K, class D, class C>
|
||||
basic_ptree<K, D, C> *
|
||||
basic_ptree<K, D, C>::walk_path(path_type &p) const
|
||||
{
|
||||
if(p.empty()) {
|
||||
// I'm the child we're looking for.
|
||||
return const_cast<basic_ptree*>(this);
|
||||
}
|
||||
// Recurse down the tree to find the path.
|
||||
key_type fragment = p.reduce();
|
||||
const_assoc_iterator el = find(fragment);
|
||||
if(el == not_found()) {
|
||||
// No such child.
|
||||
return 0;
|
||||
}
|
||||
// Not done yet, recurse.
|
||||
return el->second.walk_path(p);
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
basic_ptree<K, D, C> & basic_ptree<K, D, C>::force_path(path_type &p)
|
||||
{
|
||||
BOOST_ASSERT(!p.empty() && "Empty path not allowed for put_child.");
|
||||
if(p.single()) {
|
||||
// I'm the parent we're looking for.
|
||||
return *this;
|
||||
}
|
||||
key_type fragment = p.reduce();
|
||||
assoc_iterator el = find(fragment);
|
||||
// If we've found an existing child, go down that path. Else
|
||||
// create a new one.
|
||||
self_type& child = el == not_found() ?
|
||||
push_back(value_type(fragment, self_type()))->second : el->second;
|
||||
return child.force_path(p);
|
||||
}
|
||||
|
||||
// Free functions
|
||||
|
||||
template<class K, class D, class C>
|
||||
inline void swap(basic_ptree<K, D, C> &pt1, basic_ptree<K, D, C> &pt2)
|
||||
{
|
||||
pt1.swap(pt2);
|
||||
}
|
||||
|
||||
} }
|
||||
|
||||
#if defined(BOOST_PROPERTY_TREE_PAIR_BUG)
|
||||
#undef BOOST_PROPERTY_TREE_PAIR_BUG
|
||||
#endif
|
||||
|
||||
#endif
|
22
patched/property_tree/detail/ptree_implementation.patch
Normal file
22
patched/property_tree/detail/ptree_implementation.patch
Normal file
@ -0,0 +1,22 @@
|
||||
Index: .
|
||||
===================================================================
|
||||
--- . (revision 86520)
|
||||
+++ . (working copy)
|
||||
@@ -650,7 +650,7 @@
|
||||
}
|
||||
BOOST_PROPERTY_TREE_THROW(ptree_bad_data(
|
||||
std::string("conversion of data to type \"") +
|
||||
- typeid(Type).name() + "\" failed", data()));
|
||||
+ boost::type_id<Type>().name_demangled() + "\" failed", data()));
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
@@ -805,7 +805,7 @@
|
||||
data() = *o;
|
||||
} else {
|
||||
BOOST_PROPERTY_TREE_THROW(ptree_bad_data(
|
||||
- std::string("conversion of type \"") + typeid(Type).name() +
|
||||
+ std::string("conversion of type \"") + boost::type_id<Type>().name_demangled() +
|
||||
"\" to data failed", boost::any()));
|
||||
}
|
||||
}
|
38
patched/xpressive/linker.patch
Normal file
38
patched/xpressive/linker.patch
Normal file
@ -0,0 +1,38 @@
|
||||
Index: .
|
||||
===================================================================
|
||||
--- . (revision 86520)
|
||||
+++ . (working copy)
|
||||
@@ -19,7 +19,7 @@
|
||||
#endif
|
||||
#include <stack>
|
||||
#include <limits>
|
||||
-#include <typeinfo>
|
||||
+#include <boost/type_index/type_info.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/version.hpp>
|
||||
@@ -144,7 +144,7 @@
|
||||
explicit xpression_linker(Traits const &tr)
|
||||
: back_stack_()
|
||||
, traits_(&tr)
|
||||
- , traits_type_(&typeid(Traits))
|
||||
+ , traits_type_(&boost::type_id<Traits>())
|
||||
, has_backrefs_(false)
|
||||
{
|
||||
}
|
||||
@@ -310,13 +310,13 @@
|
||||
template<typename Traits>
|
||||
Traits const &get_traits() const
|
||||
{
|
||||
- BOOST_ASSERT(*this->traits_type_ == typeid(Traits));
|
||||
+ BOOST_ASSERT(*this->traits_type_ == boost::type_id<Traits>());
|
||||
return *static_cast<Traits const *>(this->traits_);
|
||||
}
|
||||
|
||||
std::stack<void const *> back_stack_;
|
||||
void const *traits_;
|
||||
- std::type_info const *traits_type_;
|
||||
+ boost::type_info const *traits_type_;
|
||||
bool has_backrefs_;
|
||||
};
|
||||
|
33
patched/xpressive/match_result.patch
Normal file
33
patched/xpressive/match_result.patch
Normal file
@ -0,0 +1,33 @@
|
||||
Index: .
|
||||
===================================================================
|
||||
--- . (revision 86520)
|
||||
+++ . (working copy)
|
||||
@@ -25,9 +25,9 @@
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
#include <iterator>
|
||||
-#include <typeinfo>
|
||||
#include <algorithm>
|
||||
#include <boost/config.hpp>
|
||||
+#include <boost/type_index/type_info.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/integer.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
@@ -72,7 +72,7 @@
|
||||
//
|
||||
struct type_info_less
|
||||
{
|
||||
- bool operator()(std::type_info const *left, std::type_info const *right) const
|
||||
+ bool operator()(boost::type_info const *left, boost::type_info const *right) const
|
||||
{
|
||||
return 0 != left->before(*right);
|
||||
}
|
||||
@@ -679,7 +679,7 @@
|
||||
typedef typename proto::result_of::value<right_type>::type arg_right_type;
|
||||
BOOST_MPL_ASSERT((proto::matches<Arg, detail::ActionArgBinding>));
|
||||
BOOST_MPL_ASSERT((is_same<typename arg_left_type::type, arg_right_type>));
|
||||
- this->args_[&typeid(proto::value(proto::left(arg)))] = &proto::value(proto::right(arg));
|
||||
+ this->args_[&boost::type_id<arg_left_type>()] = &proto::value(proto::right(arg));
|
||||
return *this;
|
||||
}
|
||||
|
43
patched/xpressive/peeker.patch
Normal file
43
patched/xpressive/peeker.patch
Normal file
@ -0,0 +1,43 @@
|
||||
Index: .
|
||||
===================================================================
|
||||
--- . (revision 86520)
|
||||
+++ . (working copy)
|
||||
@@ -14,7 +14,7 @@
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
-#include <typeinfo>
|
||||
+#include <boost/type_index/type_info.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/mpl/bool.hpp>
|
||||
#include <boost/mpl/assert.hpp>
|
||||
@@ -250,9 +250,9 @@
|
||||
if(0 == this->traits_)
|
||||
{
|
||||
this->traits_ = &tr;
|
||||
- this->traits_type_ = &typeid(Traits);
|
||||
+ this->traits_type_ = &boost::type_id<Traits>();
|
||||
}
|
||||
- else if(*this->traits_type_ != typeid(Traits) || this->get_traits_<Traits>() != tr)
|
||||
+ else if(*this->traits_type_ != boost::type_id<Traits>() || this->get_traits_<Traits>() != tr)
|
||||
{
|
||||
this->fail(); // traits mis-match! set all and bail
|
||||
}
|
||||
@@ -265,7 +265,7 @@
|
||||
template<typename Traits>
|
||||
Traits const &get_traits_() const
|
||||
{
|
||||
- BOOST_ASSERT(!!(*this->traits_type_ == typeid(Traits)));
|
||||
+ BOOST_ASSERT(!!(*this->traits_type_ == boost::type_id<Traits>()));
|
||||
return *static_cast<Traits const *>(this->traits_);
|
||||
}
|
||||
|
||||
@@ -274,7 +274,7 @@
|
||||
bool str_icase_;
|
||||
bool line_start_;
|
||||
void const *traits_;
|
||||
- std::type_info const *traits_type_;
|
||||
+ boost::type_info const *traits_type_;
|
||||
int leading_simple_repeat_;
|
||||
bool has_backrefs_;
|
||||
};
|
Reference in New Issue
Block a user