//
//  Copyright (c) 2000-2002
//  Joerg Walter, Mathias Koch
//
//  Permission to use, copy, modify, distribute and sell this software
//  and its documentation for any purpose is hereby granted without fee,
//  provided that the above copyright notice appear in all copies and
//  that both that copyright notice and this permission notice appear
//  in supporting documentation.  The authors make no representations
//  about the suitability of this software for any purpose.
//  It is provided "as is" without express or implied warranty.
//
//  The authors gratefully acknowledge the support of
//  GeNeSys mbH & Co. KG in producing this work.
//

#ifndef BOOST_UBLAS_TRAITS_H
#define BOOST_UBLAS_TRAITS_H

#include <algorithm>
#include <iterator>
#include <complex>
#include <cmath>

#include <boost/numeric/ublas/iterator.hpp>
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_NO_SFINAE)
#include <boost/numeric/ublas/returntype_deduction.hpp>
#endif

namespace boost { namespace numeric { namespace ublas {

    template<class T>
    struct type_traits {
        typedef type_traits<T> self_type;
        typedef T value_type;
        typedef const T &const_reference;
        typedef T &reference;

        /*
         * Don't define unknown properties
         *
        typedef T real_type;
        typedef T precision_type;

        BOOST_STATIC_CONSTANT (unsigned, plus_complexity = 0);
        BOOST_STATIC_CONSTANT (unsigned, multiplies_complexity = 0);

        static
        BOOST_UBLAS_INLINE
        real_type real (const_reference) {
        }
        static
        BOOST_UBLAS_INLINE
        real_type imag (const_reference) {
        }
        static
        BOOST_UBLAS_INLINE
        value_type conj (const_reference) {
        }

        static
        BOOST_UBLAS_INLINE
        real_type abs (const_reference) {
        }
        static
        BOOST_UBLAS_INLINE
        value_type sqrt (const_reference) {
        }

        static
        BOOST_UBLAS_INLINE
        real_type norm_1 (const_reference t) {
        }
        static
        BOOST_UBLAS_INLINE
        real_type norm_2 (const_reference t) {
        }
        static
        BOOST_UBLAS_INLINE
        real_type norm_inf (const_reference t) {
        }

        static
        BOOST_UBLAS_INLINE
        bool equals (const_reference t1, const_reference t2) {
        }
        */
        // Dummy definition for compilers that error if undefined even though it is never used
#ifdef BOOST_NO_SFINAE
        typedef void real_type;
        typedef void precision_type;
#endif
    };

    template<>
    struct type_traits<float> {
        typedef type_traits<float> self_type;
        typedef float value_type;
        typedef const value_type &const_reference;
        typedef value_type &reference;
        typedef value_type real_type;
        typedef double precision_type;

        BOOST_STATIC_CONSTANT (unsigned, plus_complexity = 1);
        BOOST_STATIC_CONSTANT (unsigned, multiplies_complexity = 1);

        static
        BOOST_UBLAS_INLINE
        real_type real (const_reference t) {
                return t;
        }
        static
        BOOST_UBLAS_INLINE
        real_type imag (const_reference /*t*/) {
                return 0;
        }
        static
        BOOST_UBLAS_INLINE
        value_type conj (const_reference t) {
                return t;
        }

        static
        BOOST_UBLAS_INLINE
        real_type abs (const_reference t) {
#if defined (BOOST_NO_STDC_NAMESPACE) || defined (BOOST_UBLAS_CMATH_BAD_STD)
            return ::fabsf (t);
#else
            return std::abs (t);
#endif
        }
        static
        BOOST_UBLAS_INLINE
        value_type sqrt (const_reference t) {
#if defined (BOOST_NO_STDC_NAMESPACE) || defined (BOOST_UBLAS_CMATH_BAD_STD)
            return ::sqrtf (t);
#else
            return std::sqrt (t);
#endif
        }

        static
        BOOST_UBLAS_INLINE
        real_type norm_1 (const_reference t) {
            return self_type::abs (t);
        }
        static
        BOOST_UBLAS_INLINE
        real_type norm_2 (const_reference t) {
            return self_type::abs (t);
        }
        static
        BOOST_UBLAS_INLINE
        real_type norm_inf (const_reference t) {
            return self_type::abs (t);
        }

        static
        BOOST_UBLAS_INLINE
        bool equals (const_reference t1, const_reference t2) {
            return self_type::norm_inf (t1 - t2) < BOOST_UBLAS_TYPE_CHECK_EPSILON *
                   (std::max) ((std::max) (self_type::norm_inf (t1),
                                       self_type::norm_inf (t2)),
                             BOOST_UBLAS_TYPE_CHECK_MIN);
        }
    };
    template<>
    struct type_traits<double> {
        typedef type_traits<double> self_type;
        typedef double value_type;
        typedef const value_type &const_reference;
        typedef value_type &reference;
        typedef value_type real_type;
#ifndef BOOST_UBLAS_NO_LONG_DOUBLE
        typedef long double precision_type;
#else
        typedef value_type precision_type;
#endif

        BOOST_STATIC_CONSTANT (unsigned, plus_complexity = 1);
        BOOST_STATIC_CONSTANT (unsigned, multiplies_complexity = 1);

        static
        BOOST_UBLAS_INLINE
        real_type real (const_reference t) {
                return t;
        }
        static
        BOOST_UBLAS_INLINE
        real_type imag (const_reference /*t*/) {
                return 0;
        }
        static
        BOOST_UBLAS_INLINE
        value_type conj (const_reference t) {
                return t;
        }

        static
        BOOST_UBLAS_INLINE
        real_type abs (const_reference t) {
#if defined (BOOST_NO_STDC_NAMESPACE) || defined (BOOST_UBLAS_CMATH_BAD_STD)
            return ::fabs (t);
#else
            return std::abs (t);
#endif
        }
        static
        BOOST_UBLAS_INLINE
        value_type sqrt (const_reference t) {
#if defined (BOOST_NO_STDC_NAMESPACE) || defined (BOOST_UBLAS_CMATH_BAD_STD)
            return ::sqrt (t);
#else
            return std::sqrt (t);
#endif
        }

        static
        BOOST_UBLAS_INLINE
        real_type norm_1 (const_reference t) {
            return self_type::abs (t);
        }
        static
        BOOST_UBLAS_INLINE
        real_type norm_2 (const_reference t) {
            return self_type::abs (t);
        }
        static
        BOOST_UBLAS_INLINE
        real_type norm_inf (const_reference t) {
            return self_type::abs (t);
        }

        static
        BOOST_UBLAS_INLINE
        bool equals (const_reference t1, const_reference t2) {
            return self_type::norm_inf (t1 - t2) < BOOST_UBLAS_TYPE_CHECK_EPSILON *
                   (std::max) ((std::max) (self_type::norm_inf (t1),
                                       self_type::norm_inf (t2)),
                             BOOST_UBLAS_TYPE_CHECK_MIN);
        }
    };
#ifndef BOOST_UBLAS_NO_LONG_DOUBLE
    template<>
    struct type_traits<long double> {
        typedef type_traits<long double> self_type;
        typedef long double value_type;
        typedef const value_type &const_reference;
        typedef value_type &reference;
        typedef value_type real_type;
        typedef value_type precision_type;

        BOOST_STATIC_CONSTANT (unsigned, plus_complexity = 1);
        BOOST_STATIC_CONSTANT (unsigned, multiplies_complexity = 1);

        static
        BOOST_UBLAS_INLINE
        real_type real (const_reference t) {
                return t;
        }
        static
        BOOST_UBLAS_INLINE
        real_type imag (const_reference /*t*/) {
                return 0;
        }
        static
        BOOST_UBLAS_INLINE
        value_type conj (const_reference t) {
                return t;
        }

        static
        BOOST_UBLAS_INLINE
        real_type abs (const_reference t) {
#if defined (BOOST_NO_STDC_NAMESPACE) || defined (BOOST_UBLAS_CMATH_BAD_STD)
            return ::fabsl (t);
#else
            return std::abs (t);
#endif
        }
        static
        BOOST_UBLAS_INLINE
        value_type sqrt (const_reference t) {
#if defined (BOOST_NO_STDC_NAMESPACE) || defined (BOOST_UBLAS_CMATH_BAD_STD)
            return ::sqrtl (t);
#else
            return std::sqrt (t);
#endif
        }

        static
        BOOST_UBLAS_INLINE
        real_type norm_1 (const_reference t) {
            return self_type::abs (t);
        }
        static
        BOOST_UBLAS_INLINE
        real_type norm_2 (const_reference t) {
            return self_type::abs (t);
        }
        static
        BOOST_UBLAS_INLINE
        real_type norm_inf (const_reference t) {
            return self_type::abs (t);
        }

        static
        BOOST_UBLAS_INLINE
        bool equals (const_reference t1, const_reference t2) {
            return self_type::norm_inf (t1 - t2) < BOOST_UBLAS_TYPE_CHECK_EPSILON *
                   (std::max) ((std::max) (self_type::norm_inf (t1),
                                       self_type::norm_inf (t2)),
                             BOOST_UBLAS_TYPE_CHECK_MIN);
        }
    };
#endif

    template<>
    struct type_traits<std::complex<float> > {
        typedef type_traits<std::complex<float> > self_type;
        typedef std::complex<float> value_type;
        typedef const value_type &const_reference;
        typedef value_type &reference;
        typedef float real_type;
        typedef std::complex<double> precision_type;

        BOOST_STATIC_CONSTANT (unsigned, plus_complexity = 2);
        BOOST_STATIC_CONSTANT (unsigned, multiplies_complexity = 6);

        static
        BOOST_UBLAS_INLINE
        real_type real (const_reference t) {
                return std::real (t);
        }
        static
        BOOST_UBLAS_INLINE
        real_type imag (const_reference t) {
                return std::imag (t);
        }
        static
        BOOST_UBLAS_INLINE
        value_type conj (const_reference t) {
                return std::conj (t);
        }

        static
        BOOST_UBLAS_INLINE
        real_type abs (const_reference t) {
                return std::abs (t);
        }
        static
        BOOST_UBLAS_INLINE
        value_type sqrt (const_reference t) {
                return std::sqrt (t);
        }

        static
        BOOST_UBLAS_INLINE
        real_type norm_1 (const_reference t) {
            return type_traits<real_type>::abs (self_type::real (t)) +
                   type_traits<real_type>::abs (self_type::imag (t));
        }
        static
        BOOST_UBLAS_INLINE
        real_type norm_2 (const_reference t) {
            return self_type::abs (t);
        }
        static
        BOOST_UBLAS_INLINE
        real_type norm_inf (const_reference t) {
            return (std::max) (type_traits<real_type>::abs (self_type::real (t)),
                             type_traits<real_type>::abs (self_type::imag (t)));
        }

        static
        BOOST_UBLAS_INLINE
        bool equals (const_reference t1, const_reference t2) {
            return self_type::norm_inf (t1 - t2) < BOOST_UBLAS_TYPE_CHECK_EPSILON *
                   (std::max) ((std::max) (self_type::norm_inf (t1),
                                       self_type::norm_inf (t2)),
                             BOOST_UBLAS_TYPE_CHECK_MIN);
        }
    };
    template<>
    struct type_traits<std::complex<double> > {
        typedef type_traits<std::complex<double> > self_type;
        typedef std::complex<double> value_type;
        typedef const value_type &const_reference;
        typedef value_type &reference;
        typedef double real_type;
#ifndef BOOST_UBLAS_NO_LONG_DOUBLE
        typedef std::complex<long double> precision_type;
#else
        typedef value_type precision_type;
#endif

        BOOST_STATIC_CONSTANT (unsigned, plus_complexity = 2);
        BOOST_STATIC_CONSTANT (unsigned, multiplies_complexity = 6);

        static
        BOOST_UBLAS_INLINE
        real_type real (const_reference t) {
                return std::real (t);
        }
        static
        BOOST_UBLAS_INLINE
        real_type imag (const_reference t) {
                return std::imag (t);
        }
        static
        BOOST_UBLAS_INLINE
        value_type conj (const_reference t) {
                return std::conj (t);
        }

        static
        BOOST_UBLAS_INLINE
        real_type abs (const_reference t) {
                return std::abs (t);
        }
        static
        BOOST_UBLAS_INLINE
        value_type sqrt (const_reference t) {
                return std::sqrt (t);
        }

        static
        BOOST_UBLAS_INLINE
        real_type norm_1 (const_reference t) {
            return type_traits<real_type>::abs (self_type::real (t)) +
                   type_traits<real_type>::abs (self_type::imag (t));
        }
        static
        BOOST_UBLAS_INLINE
        real_type norm_2 (const_reference t) {
            return self_type::abs (t);
        }
        static
        BOOST_UBLAS_INLINE
        real_type norm_inf (const_reference t) {
            return (std::max) (type_traits<real_type>::abs (self_type::real (t)),
                             type_traits<real_type>::abs (self_type::imag (t)));
        }

        static
        BOOST_UBLAS_INLINE
        bool equals (const_reference t1, const_reference t2) {
            return self_type::norm_inf (t1 - t2) < BOOST_UBLAS_TYPE_CHECK_EPSILON *
                   (std::max) ((std::max) (self_type::norm_inf (t1),
                                       self_type::norm_inf (t2)),
                             BOOST_UBLAS_TYPE_CHECK_MIN);
        }
    };
#ifndef BOOST_UBLAS_NO_LONG_DOUBLE
    template<>
    struct type_traits<std::complex<long double> > {
        typedef type_traits<std::complex<long double> > self_type;
        typedef std::complex<long double> value_type;
        typedef const value_type &const_reference;
        typedef value_type &reference;
        typedef long double real_type;
        typedef value_type precision_type;

        BOOST_STATIC_CONSTANT (unsigned, plus_complexity = 2);
        BOOST_STATIC_CONSTANT (unsigned, multiplies_complexity = 6);

        static
        BOOST_UBLAS_INLINE
        real_type real (const_reference t) {
                return std::real (t);
        }
        static
        BOOST_UBLAS_INLINE
        real_type imag (const_reference t) {
                return std::imag (t);
        }
        static
        BOOST_UBLAS_INLINE
        value_type conj (const_reference t) {
                return std::conj (t);
        }

        static
        BOOST_UBLAS_INLINE
        real_type abs (const_reference t) {
                return std::abs (t);
        }
        static
        BOOST_UBLAS_INLINE
        value_type sqrt (const_reference t) {
                return std::sqrt (t);
        }

        static
        BOOST_UBLAS_INLINE
        real_type norm_1 (const_reference t) {
            return type_traits<real_type>::abs (self_type::real (t)) +
                   type_traits<real_type>::abs (self_type::imag (t));
        }
        static
        BOOST_UBLAS_INLINE
        real_type norm_2 (const_reference t) {
            return self_type::abs (t);
        }
        static
        BOOST_UBLAS_INLINE
        real_type norm_inf (const_reference t) {
            return (std::max) (type_traits<real_type>::abs (self_type::real (t)),
                             type_traits<real_type>::abs (self_type::imag (t)));
        }

        static
        BOOST_UBLAS_INLINE
        bool equals (const_reference t1, const_reference t2) {
            return self_type::norm_inf (t1 - t2) < BOOST_UBLAS_TYPE_CHECK_EPSILON *
                   (std::max) ((std::max) (self_type::norm_inf (t1),
                                       self_type::norm_inf (t2)),
                             BOOST_UBLAS_TYPE_CHECK_MIN);
        }
    };
#endif

#ifdef BOOST_UBLAS_USE_INTERVAL
    template<>
    struct type_traits<boost::numeric::interval<float> > {
        typedef type_traits<boost::numeric::interval<float> > self_type;
        typedef boost::numeric::interval<float> value_type;
        typedef const value_type &const_reference;
        typedef value_type &reference;
        typedef value_type real_type;
        typedef boost::numeric::interval<double> precision_type;

        BOOST_STATIC_CONSTANT (unsigned, plus_complexity = 1);
        BOOST_STATIC_CONSTANT (unsigned, multiplies_complexity = 1);

        static
        BOOST_UBLAS_INLINE
        real_type real (const_reference t) {
                return t;
        }
        static
        BOOST_UBLAS_INLINE
        real_type imag (const_reference t) {
                return 0;
        }
        static
        BOOST_UBLAS_INLINE
        value_type conj (const_reference t) {
                return t;
        }

        static
        BOOST_UBLAS_INLINE
        real_type abs (const_reference t) {
            return boost::numeric::abs (t);
        }
        static
        BOOST_UBLAS_INLINE
        value_type sqrt (const_reference t) {
            return boost::numeric::sqrt (t);
        }

        static
        BOOST_UBLAS_INLINE
        real_type norm_1 (const_reference t) {
            return self_type::abs (t);
        }
        static
        BOOST_UBLAS_INLINE
        real_type norm_2 (const_reference t) {
            return self_type::abs (t);
        }
        static
        BOOST_UBLAS_INLINE
        real_type norm_inf (const_reference t) {
            return self_type::abs (t);
        }

        static
        BOOST_UBLAS_INLINE
        bool equals (const_reference t1, const_reference t2) {
            return self_type::norm_inf (t1 - t2) < BOOST_UBLAS_TYPE_CHECK_EPSILON *
                   (std::max) ((std::max) (self_type::norm_inf (t1),
                                       self_type::norm_inf (t2)),
                             BOOST_UBLAS_TYPE_CHECK_MIN);
        }
    };
    template<>
    struct type_traits<boost::numeric::interval<double> > {
        typedef type_traits<boost::numeric::interval<double> > self_type;
        typedef boost::numeric::interval<double> value_type;
        typedef const value_type &const_reference;
        typedef value_type &reference;
        typedef value_type real_type;
#ifndef BOOST_UBLAS_NO_LONG_DOUBLE
        typedef boost::numeric::interval<long double> precision_type;
#else
        typedef value_type precision_type;
#endif

        BOOST_STATIC_CONSTANT (unsigned, plus_complexity = 1);
        BOOST_STATIC_CONSTANT (unsigned, multiplies_complexity = 1);

        static
        BOOST_UBLAS_INLINE
        real_type real (const_reference t) {
                return t;
        }
        static
        BOOST_UBLAS_INLINE
        real_type imag (const_reference t) {
                return 0;
        }
        static
        BOOST_UBLAS_INLINE
        value_type conj (const_reference t) {
                return t;
        }

        static
        BOOST_UBLAS_INLINE
        real_type abs (const_reference t) {
            return boost::numeric::abs (t);
        }
        static
        BOOST_UBLAS_INLINE
        value_type sqrt (const_reference t) {
            return boost::numeric::sqrt (t);
        }

        static
        BOOST_UBLAS_INLINE
        real_type norm_1 (const_reference t) {
            return self_type::abs (t);
        }
        static
        BOOST_UBLAS_INLINE
        real_type norm_2 (const_reference t) {
            return self_type::abs (t);
        }
        static
        BOOST_UBLAS_INLINE
        real_type norm_inf (const_reference t) {
            return self_type::abs (t);
        }

        static
        BOOST_UBLAS_INLINE
        bool equals (const_reference t1, const_reference t2) {
            return self_type::norm_inf (t1 - t2) < BOOST_UBLAS_TYPE_CHECK_EPSILON *
                   (std::max) ((std::max) (self_type::norm_inf (t1),
                                       self_type::norm_inf (t2)),
                             BOOST_UBLAS_TYPE_CHECK_MIN);
        }
    };
#ifndef BOOST_UBLAS_NO_LONG_DOUBLE
    template<>
    struct type_traits<boost::numeric::interval<long double> > {
        typedef type_traits<boost::numeric::interval<long double> > self_type;
        typedef boost::numeric::interval<long double> value_type;
        typedef const value_type &const_reference;
        typedef value_type &reference;
        typedef value_type real_type;
        typedef value_type precision_type;

        BOOST_STATIC_CONSTANT (unsigned, plus_complexity = 1);
        BOOST_STATIC_CONSTANT (unsigned, multiplies_complexity = 1);

        static
        BOOST_UBLAS_INLINE
        real_type real (const_reference t) {
                return t;
        }
        static
        BOOST_UBLAS_INLINE
        real_type imag (const_reference t) {
                return 0;
        }
        static
        BOOST_UBLAS_INLINE
        value_type conj (const_reference t) {
                return t;
        }

        static
        BOOST_UBLAS_INLINE
        real_type abs (const_reference t) {
            return boost::numeric::abs (t);
        }
        static
        BOOST_UBLAS_INLINE
        value_type sqrt (const_reference t) {
            return boost::numeric::sqrt (t);
        }

        static
        BOOST_UBLAS_INLINE
        real_type norm_1 (const_reference t) {
            return self_type::abs (t);
        }
        static
        BOOST_UBLAS_INLINE
        real_type norm_2 (const_reference t) {
            return self_type::abs (t);
        }
        static
        BOOST_UBLAS_INLINE
        real_type norm_inf (const_reference t) {
            return self_type::abs (t);
        }

        static
        BOOST_UBLAS_INLINE
        bool equals (const_reference t1, const_reference t2) {
            return self_type::norm_inf (t1 - t2) < BOOST_UBLAS_TYPE_CHECK_EPSILON *
                   (std::max) ((std::max) (self_type::norm_inf (t1),
                                       self_type::norm_inf (t2)),
                             BOOST_UBLAS_TYPE_CHECK_MIN);
        }
    };
#endif

#ifdef BOOST_UBLAS_USE_BOOST_COMPLEX
    template<>
    struct type_traits<boost::complex<boost::numeric::interval<float> > > {
        typedef type_traits<boost::complex<boost::numeric::interval<float> > > self_type;
        typedef boost::complex<boost::numeric::interval<float> > value_type;
        typedef const value_type &const_reference;
        typedef value_type &reference;
        typedef boost::numeric::interval<float> real_type;
        typedef boost::complex<boost::numeric::interval<double> > precision_type;

        BOOST_STATIC_CONSTANT (unsigned, plus_complexity = 2);
        BOOST_STATIC_CONSTANT (unsigned, multiplies_complexity = 6);

        static
        BOOST_UBLAS_INLINE
        real_type real (const_reference t) {
                return std::real (t);
        }
        static
        BOOST_UBLAS_INLINE
        real_type imag (const_reference t) {
                return std::imag (t);
        }
        static
        BOOST_UBLAS_INLINE
        value_type conj (const_reference t) {
                return std::conj (t);
        }

        static
        BOOST_UBLAS_INLINE
        real_type abs (const_reference t) {
                return boost::numeric::abs (t);
        }
        static
        BOOST_UBLAS_INLINE
        value_type sqrt (const_reference t) {
                return boost::numeric::sqrt (t);
        }

        static
        BOOST_UBLAS_INLINE
        real_type norm_1 (const_reference t) {
            return type_traits<real_type>::abs (self_type::real (t)) +
                   type_traits<real_type>::abs (self_type::imag (t));
        }
        static
        BOOST_UBLAS_INLINE
        real_type norm_2 (const_reference t) {
            return self_type::abs (t);
        }
        static
        BOOST_UBLAS_INLINE
        real_type norm_inf (const_reference t) {
            return (std::max) (type_traits<real_type>::abs (self_type::real (t)),
                             type_traits<real_type>::abs (self_type::imag (t)));
        }

        static
        BOOST_UBLAS_INLINE
        bool equals (const_reference t1, const_reference t2) {
            return self_type::norm_inf (t1 - t2) < BOOST_UBLAS_TYPE_CHECK_EPSILON *
                   (std::max) ((std::max) (self_type::norm_inf (t1),
                                       self_type::norm_inf (t2)),
                             BOOST_UBLAS_TYPE_CHECK_MIN);
        }
    };
    template<>
    struct type_traits<boost::complex<boost::numeric::interval<double> > {
        typedef type_traits<boost::complex<boost::numeric::interval<double> > self_type;
        typedef boost::complex<boost::numeric::interval<double> > value_type;
        typedef const value_type &const_reference;
        typedef value_type &reference;
        typedef boost::numeric::interval<double> real_type;
#ifndef BOOST_UBLAS_NO_LONG_DOUBLE
        typedef boost::complex<boost::numeric::interval<long double> > precision_type;
#else
        typedef value_type precision_type;
#endif

        BOOST_STATIC_CONSTANT (unsigned, plus_complexity = 2);
        BOOST_STATIC_CONSTANT (unsigned, multiplies_complexity = 6);

        static
        BOOST_UBLAS_INLINE
        real_type real (const_reference t) {
                return std::real (t);
        }
        static
        BOOST_UBLAS_INLINE
        real_type imag (const_reference t) {
                return std::imag (t);
        }
        static
        BOOST_UBLAS_INLINE
        value_type conj (const_reference t) {
                return std::conj (t);
        }

        static
        BOOST_UBLAS_INLINE
        real_type abs (const_reference t) {
                return boost::numeric::abs (t);
        }
        static
        BOOST_UBLAS_INLINE
        value_type sqrt (const_reference t) {
                return boost::numeric::sqrt (t);
        }

        static
        BOOST_UBLAS_INLINE
        real_type norm_1 (const_reference t) {
            return type_traits<real_type>::abs (self_type::real (t)) +
                   type_traits<real_type>::abs (self_type::imag (t));
        }
        static
        BOOST_UBLAS_INLINE
        real_type norm_2 (const_reference t) {
            return self_type::abs (t);
        }
        static
        BOOST_UBLAS_INLINE
        real_type norm_inf (const_reference t) {
            return (std::max) (type_traits<real_type>::abs (self_type::real (t)),
                             type_traits<real_type>::abs (self_type::imag (t)));
        }

        static
        BOOST_UBLAS_INLINE
        bool equals (const_reference t1, const_reference t2) {
            return self_type::norm_inf (t1 - t2) < BOOST_UBLAS_TYPE_CHECK_EPSILON *
                   (std::max) ((std::max) (self_type::norm_inf (t1),
                                       self_type::norm_inf (t2)),
                             BOOST_UBLAS_TYPE_CHECK_MIN);
        }
    };
#ifndef BOOST_UBLAS_NO_LONG_DOUBLE
    template<>
    struct type_traits<boost::complex<boost::numeric::interval<long double> > > {
        typedef type_traits<boost::complex<boost::numeric::interval<long double> > > self_type;
        typedef boost::complex<boost::numeric::interval<long double> > value_type;
        typedef const value_type &const_reference;
        typedef value_type &reference;
        typedef boost::numeric::interval<long double> real_type;
        typedef value_type precision_type;

        BOOST_STATIC_CONSTANT (unsigned, plus_complexity = 2);
        BOOST_STATIC_CONSTANT (unsigned, multiplies_complexity = 6);

        static
        BOOST_UBLAS_INLINE
        real_type real (const_reference t) {
                return std::real (t);
        }
        static
        BOOST_UBLAS_INLINE
        real_type imag (const_reference t) {
                return std::imag (t);
        }
        static
        BOOST_UBLAS_INLINE
        value_type conj (const_reference t) {
                return std::conj (t);
        }

        static
        BOOST_UBLAS_INLINE
        real_type abs (const_reference t) {
                return boost::numeric::abs (t);
        }
        static
        BOOST_UBLAS_INLINE
        value_type sqrt (const_reference t) {
                return boost::numeric::sqrt (t);
        }

        static
        BOOST_UBLAS_INLINE
        real_type norm_1 (const_reference t) {
            return type_traits<real_type>::abs (self_type::real (t)) +
                   type_traits<real_type>::abs (self_type::imag (t));
        }
        static
        BOOST_UBLAS_INLINE
        real_type norm_2 (const_reference t) {
            return self_type::abs (t);
        }
        static
        BOOST_UBLAS_INLINE
        real_type norm_inf (const_reference t) {
            return (std::max) (type_traits<real_type>::abs (self_type::real (t)),
                             type_traits<real_type>::abs (self_type::imag (t)));
        }

        static
        BOOST_UBLAS_INLINE
        bool equals (const_reference t1, const_reference t2) {
            return self_type::norm_inf (t1 - t2) < BOOST_UBLAS_TYPE_CHECK_EPSILON *
                   (std::max) ((std::max) (self_type::norm_inf (t1),
                                       self_type::norm_inf (t2)),
                             BOOST_UBLAS_TYPE_CHECK_MIN);
        }
    };
#endif
#endif
#endif

#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_NO_SFINAE)
    // Use Joel de Guzman's return type deduction
    // uBLAS assumes a common return type for all binary arithmetic operators
    template<class X, class Y>
    struct promote_traits {
        typedef type_deduction_detail::base_result_of<X, Y> base_type;
        static typename base_type::x_type x;
        static typename base_type::y_type y;
        BOOST_STATIC_CONSTANT(int,
            size = sizeof(
                type_deduction_detail::test<
                    typename base_type::x_type
                  , typename base_type::y_type
                >(x + y)     // Use x+y to stand of all the arithmetic actions
            ));

        BOOST_STATIC_CONSTANT(int, index = (size / sizeof(char)) - 1);
        typedef typename mpl::at_c<
            typename base_type::types, index>::type id;
        typedef typename id::type promote_type;
    };
    template<class X, class Y>
    struct promote_type_multiplies {
        typedef type_deduction_detail::base_result_of<X, Y> base_type;
        static typename base_type::x_type x;
        static typename base_type::y_type y;
        BOOST_STATIC_CONSTANT(int,
            size = sizeof(
                type_deduction_detail::test<
                    typename base_type::x_type
                  , typename base_type::y_type
                >(x * y)     // Specifically the * arithmetic actions
            ));

        BOOST_STATIC_CONSTANT(int, index = (size / sizeof(char)) - 1);
        typedef typename mpl::at_c<
            typename base_type::types, index>::type id;
        typedef typename id::type promote_type;
    };

#else
    template<class T1, class T2>
    struct promote_traits {
        // Default promotion will badly fail, if the types are different.
        // Thanks to Kresimir Fresl for spotting this.
        BOOST_STATIC_ASSERT ((boost::is_same<T1, T2>::value));
        typedef T1 promote_type;
    };

    template<>
    struct promote_traits<float, double> {
        typedef double promote_type;
    };
    template<>
    struct promote_traits<double, float> {
        typedef double promote_type;
    };
#ifndef BOOST_UBLAS_NO_LONG_DOUBLE
    template<>
    struct promote_traits<float, long double> {
        typedef long double promote_type;
    };
    template<>
    struct promote_traits<long double, float> {
        typedef long double promote_type;
    };
    template<>
    struct promote_traits<double, long double> {
        typedef long double promote_type;
    };
    template<>
    struct promote_traits<long double, double> {
        typedef long double promote_type;
    };
#endif

    template<>
    struct promote_traits<float, std::complex<float> > {
        typedef std::complex<float> promote_type;
    };
    template<>
    struct promote_traits<std::complex<float>, float> {
        typedef std::complex<float> promote_type;
    };
    template<>
    struct promote_traits<float, std::complex<double> > {
        typedef std::complex<double> promote_type;
    };
    template<>
    struct promote_traits<std::complex<double>, float> {
        typedef std::complex<double> promote_type;
    };
#ifndef BOOST_UBLAS_NO_LONG_DOUBLE
    template<>
    struct promote_traits<float, std::complex<long double> > {
        typedef std::complex<long double> promote_type;
    };
    template<>
    struct promote_traits<std::complex<long double>, float> {
        typedef std::complex<long double> promote_type;
    };
#endif

    template<>
    struct promote_traits<double, std::complex<float> > {
        // Here we'd better go the conservative way.
        // typedef std::complex<float> promote_type;
        typedef std::complex<double> promote_type;
    };
    template<>
    struct promote_traits<std::complex<float>, double> {
        // Here we'd better go the conservative way.
        // typedef std::complex<float> promote_type;
        typedef std::complex<double> promote_type;
    };
    template<>
    struct promote_traits<double, std::complex<double> > {
        typedef std::complex<double> promote_type;
    };
    template<>
    struct promote_traits<std::complex<double>, double> {
        typedef std::complex<double> promote_type;
    };
#ifndef BOOST_UBLAS_NO_LONG_DOUBLE
    template<>
    struct promote_traits<double, std::complex<long double> > {
        typedef std::complex<long double> promote_type;
    };
    template<>
    struct promote_traits<std::complex<long double>, double> {
        typedef std::complex<long double> promote_type;
    };
#endif

#ifndef BOOST_UBLAS_NO_LONG_DOUBLE
    template<>
    struct promote_traits<long double, std::complex<float> > {
        // Here we'd better go the conservative way.
        // typedef std::complex<float> promote_type;
        typedef std::complex<long double> promote_type;
    };
    template<>
    struct promote_traits<std::complex<float>, long double> {
        // Here we'd better go the conservative way.
        // typedef std::complex<float> promote_type;
        typedef std::complex<long double> promote_type;
    };
    template<>
    struct promote_traits<long double, std::complex<double> > {
        // Here we'd better go the conservative way.
        // typedef std::complex<double> promote_type;
        typedef std::complex<long double> promote_type;
    };
    template<>
    struct promote_traits<std::complex<double>, long double> {
        // Here we'd better go the conservative way.
        // typedef std::complex<double> promote_type;
        typedef std::complex<long double> promote_type;
    };
    template<>
    struct promote_traits<long double, std::complex<long double> > {
        typedef std::complex<long double> promote_type;
    };
    template<>
    struct promote_traits<std::complex<long double>, long double> {
        typedef std::complex<long double> promote_type;
    };
#endif

    template<>
    struct promote_traits<std::complex<float>, std::complex<double> > {
        typedef std::complex<double> promote_type;
    };
    template<>
    struct promote_traits<std::complex<double>, std::complex<float> > {
        typedef std::complex<double> promote_type;
    };
#ifndef BOOST_UBLAS_NO_LONG_DOUBLE
    template<>
    struct promote_traits<std::complex<float>, std::complex<long double> > {
        typedef std::complex<long double> promote_type;
    };
    template<>
    struct promote_traits<std::complex<long double>, std::complex<float> > {
        typedef std::complex<long double> promote_type;
    };
    template<>
    struct promote_traits<std::complex<double>, std::complex<long double> > {
        typedef std::complex<long double> promote_type;
    };
    template<>
    struct promote_traits<std::complex<long double>, std::complex<double> > {
        typedef std::complex<long double> promote_type;
    };
#endif

#ifdef BOOST_UBLAS_USE_INTERVAL
    template<>
    struct promote_traits<boost::numeric::interval<float>, boost::numeric::interval<double> > {
        typedef boost::numeric::interval<double> promote_type;
    };
    template<>
    struct promote_traits<boost::numeric::interval<double>, boost::numeric::interval<float> > {
        typedef boost::numeric::interval<double> promote_type;
    };
#ifndef BOOST_UBLAS_NO_LONG_DOUBLE
    template<>
    struct promote_traits<boost::numeric::interval<float>, boost::numeric::interval<long double> > {
        typedef boost::numeric::interval<long double> promote_type;
    };
    template<>
    struct promote_traits<boost::numeric::interval<long double>, boost::numeric::interval<float> > {
        typedef boost::numeric::interval<long double> promote_type;
    };
    template<>
    struct promote_traits<boost::numeric::interval<double>, boost::numeric::interval<long double> > {
        typedef boost::numeric::interval<long double> promote_type;
    };
    template<>
    struct promote_traits<boost::numeric::interval<long double>, boost::numeric::interval<double> > {
        typedef boost::numeric::interval<long double> promote_type;
    };
#endif

#ifdef BOOST_UBLAS_USE_BOOST_COMPLEX
    template<>
    struct promote_traits<boost::numeric::interval<float>, boost::complex<boost::numeric::interval<float> > > {
        typedef boost::complex<boost::numeric::interval<float> > promote_type;
    };
    template<>
    struct promote_traits<boost::complex<boost::numeric::interval<float> >, boost::numeric::interval<float> > {
        typedef boost::complex<boost::numeric::interval<float> > promote_type;
    };
    template<>
    struct promote_traits<boost::numeric::interval<float>, boost::complex<boost::numeric::interval<double> > > {
        typedef boost::complex<boost::numeric::interval<double> > promote_type;
    };
    template<>
    struct promote_traits<boost::complex<boost::numeric::interval<double> >, boost::numeric::interval<float> > {
        typedef boost::complex<boost::numeric::interval<double> > promote_type;
    };
#ifndef BOOST_UBLAS_NO_LONG_DOUBLE
    template<>
    struct promote_traits<boost::numeric::interval<float>, boost::complex<boost::numeric::interval<long double> > > {
        typedef boost::complex<boost::numeric::interval<long double> > promote_type;
    };
    template<>
    struct promote_traits<boost::complex<boost::numeric::interval<long double> >, boost::numeric::interval<float> > {
        typedef boost::complex<boost::numeric::interval<long double> > promote_type;
    };
#endif

    template<>
    struct promote_traits<boost::numeric::interval<double>, boost::complex<boost::numeric::interval<float> > > {
        // Here we'd better go the conservative way.
        // typedef boost::complex<boost::numeric::interval<float> > promote_type;
        typedef boost::complex<boost::numeric::interval<double> > promote_type;
    };
    template<>
    struct promote_traits<boost::complex<boost::numeric::interval<float> >, boost::numeric::interval<double> > {
        // Here we'd better go the conservative way.
        // typedef boost::complex<boost::numeric::interval<float> > promote_type;
        typedef boost::complex<boost::numeric::interval<double> > promote_type;
    };
    template<>
    struct promote_traits<boost::numeric::interval<double>, boost::complex<boost::numeric::interval<double> > > {
        typedef boost::complex<boost::numeric::interval<double> > promote_type;
    };
    template<>
    struct promote_traits<boost::complex<boost::numeric::interval<double> >, boost::numeric::interval<double> > {
        typedef boost::complex<boost::numeric::interval<double> > promote_type;
    };
#ifndef BOOST_UBLAS_NO_LONG_DOUBLE
    template<>
    struct promote_traits<boost::numeric::interval<double>, boost::complex<boost::numeric::interval<long double> > > {
        typedef boost::complex<boost::numeric::interval<long double> > promote_type;
    };
    template<>
    struct promote_traits<boost::complex<boost::numeric::interval<long double> >, boost::numeric::interval<double> > {
        typedef boost::complex<boost::numeric::interval<long double> > promote_type;
    };
#endif

#ifndef BOOST_UBLAS_NO_LONG_DOUBLE
    template<>
    struct promote_traits<boost::numeric::interval<long double>, boost::complex<boost::numeric::interval<float> > > {
        // Here we'd better go the conservative way.
        // typedef boost::complex<boost::numeric::interval<float> > promote_type;
        typedef boost::complex<boost::numeric::interval<long double> > promote_type;
    };
    template<>
    struct promote_traits<boost::complex<boost::numeric::interval<float> >, boost::numeric::interval<long double> > {
        // Here we'd better go the conservative way.
        // typedef boost::complex<boost::numeric::interval<float> > promote_type;
        typedef boost::complex<boost::numeric::interval<long double> > promote_type;
    };
    template<>
    struct promote_traits<boost::numeric::interval<long double>, boost::complex<boost::numeric::interval<double> > > {
        // Here we'd better go the conservative way.
        // typedef boost::complex<boost::numeric::interval<double> > promote_type;
        typedef boost::complex<boost::numeric::interval<long double> > promote_type;
    };
    template<>
    struct promote_traits<boost::complex<boost::numeric::interval<double> >, boost::numeric::interval<long double> > {
        // Here we'd better go the conservative way.
        // typedef boost::complex<boost::numeric::interval<double> > promote_type;
        typedef boost::complex<boost::numeric::interval<long double> > promote_type;
    };
    template<>
    struct promote_traits<boost::numeric::interval<long double>, boost::complex<boost::numeric::interval<long double> > > {
        typedef boost::complex<boost::numeric::interval<long double> > promote_type;
    };
    template<>
    struct promote_traits<boost::complex<boost::numeric::interval<long double> >, boost::numeric::interval<long double> > {
        typedef boost::complex<boost::numeric::interval<long double> > promote_type;
    };
#endif

    template<>
    struct promote_traits<boost::complex<boost::numeric::interval<float> >, boost::complex<boost::numeric::interval<double> > > {
        typedef boost::complex<boost::numeric::interval<double> > promote_type;
    };
    template<>
    struct promote_traits<boost::complex<boost::numeric::interval<double> >, boost::complex<boost::numeric::interval<float> > > {
        typedef boost::complex<boost::numeric::interval<double> > promote_type;
    };
#ifndef BOOST_UBLAS_NO_LONG_DOUBLE
    template<>
    struct promote_traits<boost::complex<boost::numeric::interval<float> >, boost::complex<boost::numeric::interval<long double> > > {
        typedef boost::complex<boost::numeric::interval<long double> > promote_type;
    };
    template<>
    struct promote_traits<boost::complex<boost::numeric::interval<long double> >, boost::complex<boost::numeric::interval<float> > > {
        typedef boost::complex<boost::numeric::interval<long double> > promote_type;
    };
    template<>
    struct promote_traits<boost::complex<boost::numeric::interval<double> >, boost::complex<boost::numeric::interval<long double> > > {
        typedef boost::complex<boost::numeric::interval<long double> > promote_type;
    };
    template<>
    struct promote_traits<boost::complex<boost::numeric::interval<long double> >, boost::complex<boost::numeric::interval<double> > > {
        typedef boost::complex<boost::numeric::interval<long double> > promote_type;
    };
#endif
#endif
#endif
#endif

    struct unknown_storage_tag {};
    struct sparse_proxy_tag: public unknown_storage_tag {};
    struct sparse_tag: public sparse_proxy_tag {};
    struct packed_proxy_tag: public sparse_proxy_tag {};
    struct packed_tag: public packed_proxy_tag {};
    struct dense_proxy_tag: public packed_proxy_tag {};
    struct dense_tag: public dense_proxy_tag {};

    template<class S1, class S2>
    struct storage_restrict_traits {
        typedef S1 storage_category;
    };

    template<>
    struct storage_restrict_traits<sparse_tag, dense_proxy_tag> {
        typedef sparse_proxy_tag storage_category;
    };
    template<>
    struct storage_restrict_traits<sparse_tag, packed_proxy_tag> {
        typedef sparse_proxy_tag storage_category;
    };
    template<>
    struct storage_restrict_traits<sparse_tag, sparse_proxy_tag> {
        typedef sparse_proxy_tag storage_category;
    };

    template<>
    struct storage_restrict_traits<packed_tag, dense_proxy_tag> {
        typedef packed_proxy_tag storage_category;
    };
    template<>
    struct storage_restrict_traits<packed_tag, packed_proxy_tag> {
        typedef packed_proxy_tag storage_category;
    };
    template<>
    struct storage_restrict_traits<packed_tag, sparse_proxy_tag> {
        typedef sparse_proxy_tag storage_category;
    };

    template<>
    struct storage_restrict_traits<packed_proxy_tag, sparse_proxy_tag> {
        typedef sparse_proxy_tag storage_category;
    };

    template<>
    struct storage_restrict_traits<dense_tag, dense_proxy_tag> {
        typedef dense_proxy_tag storage_category;
    };
    template<>
    struct storage_restrict_traits<dense_tag, packed_proxy_tag> {
        typedef packed_proxy_tag storage_category;
    };
    template<>
    struct storage_restrict_traits<dense_tag, sparse_proxy_tag> {
        typedef sparse_proxy_tag storage_category;
    };

    template<>
    struct storage_restrict_traits<dense_proxy_tag, packed_proxy_tag> {
        typedef packed_proxy_tag storage_category;
    };
    template<>
    struct storage_restrict_traits<dense_proxy_tag, sparse_proxy_tag> {
        typedef sparse_proxy_tag storage_category;
    };

    struct sparse_bidirectional_iterator_tag : public std::bidirectional_iterator_tag {};
    struct packed_random_access_iterator_tag : public std::random_access_iterator_tag {};
    struct dense_random_access_iterator_tag : public packed_random_access_iterator_tag {};

    // Thanks to Kresimir Fresl for convincing Comeau with iterator_base_traits ;-)
    template<class IC>
    struct iterator_base_traits {};

    template<>
    struct iterator_base_traits<std::forward_iterator_tag> {
        template<class I, class T>
        struct iterator_base {
            typedef forward_iterator_base<std::forward_iterator_tag, I, T> type;
        };
    };

    template<>
    struct iterator_base_traits<std::bidirectional_iterator_tag> {
        template<class I, class T>
        struct iterator_base {
            typedef bidirectional_iterator_base<std::bidirectional_iterator_tag, I, T> type;
        };
    };
    template<>
    struct iterator_base_traits<sparse_bidirectional_iterator_tag> {
        template<class I, class T>
        struct iterator_base {
            typedef bidirectional_iterator_base<sparse_bidirectional_iterator_tag, I, T> type;
        };
    };

    template<>
    struct iterator_base_traits<std::random_access_iterator_tag> {
        template<class I, class T>
        struct iterator_base {
            typedef random_access_iterator_base<std::random_access_iterator_tag, I, T> type;
        };
    };
    template<>
    struct iterator_base_traits<packed_random_access_iterator_tag> {
        template<class I, class T>
        struct iterator_base {
            typedef random_access_iterator_base<packed_random_access_iterator_tag, I, T> type;
        };
    };
    template<>
    struct iterator_base_traits<dense_random_access_iterator_tag> {
        template<class I, class T>
        struct iterator_base {
            typedef random_access_iterator_base<dense_random_access_iterator_tag, I, T> type;
        };
    };

    template<class I1, class I2>
    struct iterator_restrict_traits {
        typedef I1 iterator_category;
    };

    template<>
    struct iterator_restrict_traits<packed_random_access_iterator_tag, sparse_bidirectional_iterator_tag> {
        typedef sparse_bidirectional_iterator_tag iterator_category;
    };
    template<>
    struct iterator_restrict_traits<sparse_bidirectional_iterator_tag, packed_random_access_iterator_tag> {
        typedef sparse_bidirectional_iterator_tag iterator_category;
    };

    template<>
    struct iterator_restrict_traits<dense_random_access_iterator_tag, sparse_bidirectional_iterator_tag> {
        typedef sparse_bidirectional_iterator_tag iterator_category;
    };
    template<>
    struct iterator_restrict_traits<sparse_bidirectional_iterator_tag, dense_random_access_iterator_tag> {
        typedef sparse_bidirectional_iterator_tag iterator_category;
    };

    template<>
    struct iterator_restrict_traits<dense_random_access_iterator_tag, packed_random_access_iterator_tag> {
        typedef packed_random_access_iterator_tag iterator_category;
    };
    template<>
    struct iterator_restrict_traits<packed_random_access_iterator_tag, dense_random_access_iterator_tag> {
        typedef packed_random_access_iterator_tag iterator_category;
    };

    template<class I>
    BOOST_UBLAS_INLINE
    void increment (I &it, const I &it_end, BOOST_UBLAS_TYPENAME I::difference_type compare, packed_random_access_iterator_tag) {
        it += (std::min) (compare, it_end - it);
    }
    template<class I>
    BOOST_UBLAS_INLINE
    void increment (I &it, const I &/* it_end */, BOOST_UBLAS_TYPENAME I::difference_type /* compare */, sparse_bidirectional_iterator_tag) {
        ++ it;
    }
    template<class I>
    BOOST_UBLAS_INLINE
    void increment (I &it, const I &it_end, BOOST_UBLAS_TYPENAME I::difference_type compare) {
        increment (it, it_end, compare, BOOST_UBLAS_TYPENAME I::iterator_category ());
    }

    template<class I>
    BOOST_UBLAS_INLINE
    void increment (I &it, const I &it_end) {
#if BOOST_UBLAS_TYPE_CHECK
        I cit (it);
        while (cit != it_end) {
            BOOST_UBLAS_CHECK (*cit == BOOST_UBLAS_TYPENAME I::value_type (0), internal_logic ());
            ++ cit;
        }
#endif
        it = it_end;
    }

}}}

#endif


// Copyright (c) Jeremy Siek 2001
// Copyright (c) Douglas Gregor 2004
//
// 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)

// NOTE: this final is generated by libs/graph/doc/biconnected_components.w

#ifndef BOOST_GRAPH_BICONNECTED_COMPONENTS_HPP
#define BOOST_GRAPH_BICONNECTED_COMPONENTS_HPP

#include <stack>
#include <vector>
#include <algorithm> // for std::min and std::max
#include <boost/config.hpp>
#include <boost/limits.hpp>
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/graph_concepts.hpp>
#include <boost/property_map.hpp>
#include <boost/graph/depth_first_search.hpp>
#include <boost/graph/graph_utility.hpp>

namespace boost
{
  namespace detail
  {
    template<typename ComponentMap, typename DiscoverTimeMap,
             typename LowPointMap, typename PredecessorMap,
             typename OutputIterator, typename Stack>
    struct biconnected_components_visitor : public dfs_visitor<>
    {
      biconnected_components_visitor
        (ComponentMap comp, std::size_t& c, DiscoverTimeMap dtm,
         std::size_t& dfs_time, LowPointMap lowpt, PredecessorMap pred,
         OutputIterator out, Stack& S)
          : comp(comp), c(c), dtm(dtm), dfs_time(dfs_time), lowpt(lowpt),
            pred(pred), out(out), S(S) { }

      template <typename Vertex, typename Graph>
      void start_vertex(const Vertex& u, Graph&)
      {
        put(pred, u, u);
      }

      template <typename Vertex, typename Graph>
      void discover_vertex(const Vertex& u, Graph&)
      {
        put(dtm, u, ++dfs_time);
        put(lowpt, u, get(dtm, u));
      }

      template <typename Edge, typename Graph>
      void tree_edge(const Edge& e, Graph& g)
      {
        S.push(e);
        put(pred, target(e, g), source(e, g));
      }

      template <typename Edge, typename Graph>
      void back_edge(const Edge& e, Graph& g)
      {
        BOOST_USING_STD_MIN();

        if ( target(e, g) != get(pred, source(e, g)) ) {
          S.push(e);
          put(lowpt, source(e, g),
              min BOOST_PREVENT_MACRO_SUBSTITUTION(get(lowpt, source(e, g)),
                                                   get(dtm, target(e, g))));
        }
      }

      template <typename Vertex, typename Graph>
      void finish_vertex(const Vertex& u, Graph& g)
      {
        BOOST_USING_STD_MIN();
        Vertex parent = get(pred, u);
        bool is_art_point = false;
        if ( get(dtm, parent) > get(dtm, u) ) {
          parent = get(pred, parent);
          is_art_point = true;
        }

        if ( parent == u ) { // at top
          if ( get(dtm, u) + 1 == get(dtm, get(pred, u)) )
            is_art_point = false;
        } else {
          put(lowpt, parent,
              min BOOST_PREVENT_MACRO_SUBSTITUTION(get(lowpt, parent),
                                                   get(lowpt, u)));

          if (get(lowpt, u) >= get(dtm, parent)) {
            if ( get(dtm, parent) > get(dtm, get(pred, parent)) ) {
              put(pred, u, get(pred, parent));
              put(pred, parent, u);
            }

            while ( get(dtm, source(S.top(), g)) >= get(dtm, u) ) {
              put(comp, S.top(), c);
              S.pop();
            }
            put(comp, S.top(), c);
              S.pop();
            ++c;
            if ( S.empty() ) {
              put(pred, u, parent);
              put(pred, parent, u);
            }
          }
        }
        if ( is_art_point )
          *out++ = u;
      }

      ComponentMap comp;
      std::size_t& c;
      DiscoverTimeMap dtm;
      std::size_t& dfs_time;
      LowPointMap lowpt;
      PredecessorMap pred;
      OutputIterator out;
      Stack& S;
    };
  } // namespace detail

  template<typename Graph, typename ComponentMap, typename OutputIterator,
           typename DiscoverTimeMap, typename LowPointMap,
           typename PredecessorMap, typename VertexIndexMap>
  std::pair<std::size_t, OutputIterator>
  biconnected_components(const Graph & g, ComponentMap comp,
                         OutputIterator out, DiscoverTimeMap discover_time,
                         LowPointMap lowpt, PredecessorMap pred,
                         VertexIndexMap index_map)
  {
    typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
    typedef typename graph_traits<Graph>::edge_descriptor edge_t;
    function_requires<VertexListGraphConcept<Graph> >();
    function_requires<IncidenceGraphConcept<Graph> >();
    function_requires<WritablePropertyMapConcept<ComponentMap, edge_t> >();
    function_requires<ReadWritePropertyMapConcept<DiscoverTimeMap,
                                                  vertex_t> >();
    function_requires<ReadWritePropertyMapConcept<LowPointMap, vertex_t > >();
    function_requires<ReadWritePropertyMapConcept<PredecessorMap,
                                                  vertex_t> >();

    std::size_t num_components = 0;
    std::size_t dfs_time = 0;
    std::stack < edge_t > S;

    detail::biconnected_components_visitor<ComponentMap, DiscoverTimeMap,
        LowPointMap, PredecessorMap, OutputIterator, std::stack<edge_t> >
      vis(comp, num_components, discover_time, dfs_time, lowpt, pred, out, S);

    depth_first_search(g, visitor(vis).vertex_index_map(index_map));

    return std::pair<std::size_t, OutputIterator>(num_components, vis.out);
  }

  template<typename Graph, typename ComponentMap, typename OutputIterator,
           typename DiscoverTimeMap, typename LowPointMap,
           typename VertexIndexMap>
  std::pair<std::size_t, OutputIterator>
  biconnected_components(const Graph & g, ComponentMap comp,
                         OutputIterator out, DiscoverTimeMap discover_time,
                         LowPointMap lowpt, VertexIndexMap index_map)
  {
    typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
    std::vector<vertex_t> pred(num_vertices(g));
    vertex_t vert = graph_traits<Graph>::null_vertex();
    return biconnected_components
             (g, comp, out, discover_time, lowpt,
              make_iterator_property_map(pred.begin(), index_map, vert),
              index_map);
  }

  template<typename Graph, typename ComponentMap, typename OutputIterator,
           typename VertexIndexMap>
  std::pair<std::size_t, OutputIterator>
  biconnected_components(const Graph& g, ComponentMap comp, OutputIterator out,
                         VertexIndexMap index_map)
  {
    typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
    typedef typename graph_traits<Graph>::vertices_size_type
      vertices_size_type;

    std::vector<vertices_size_type> discover_time(num_vertices(g));
    std::vector<vertices_size_type> lowpt(num_vertices(g));

    vertices_size_type vst(0);

    return biconnected_components
             (g, comp, out,
              make_iterator_property_map(discover_time.begin(), index_map, vst),
              make_iterator_property_map(lowpt.begin(), index_map, vst),
              index_map);
  }

  template < typename Graph, typename ComponentMap, typename OutputIterator>
  std::pair<std::size_t, OutputIterator>
  biconnected_components(const Graph& g, ComponentMap comp, OutputIterator out)
  {
    return biconnected_components(g, comp, out, get(vertex_index, g));
  }

  namespace graph_detail {
    struct dummy_output_iterator
    {
      typedef std::output_iterator_tag iterator_category;
      typedef void value_type;
      typedef void pointer;
      typedef void difference_type;

      struct reference {
        template<typename T>
        reference& operator=(const T&) { return *this; }
      };

      reference operator*() const { return reference(); }
      dummy_output_iterator& operator++() { return *this; }
      dummy_output_iterator operator++(int) { return *this; }
    };
  } // end namespace graph_detail

  template <typename Graph, typename ComponentMap>
  std::size_t
  biconnected_components(const Graph& g, ComponentMap comp)
  {
    return biconnected_components(g, comp,
                                  graph_detail::dummy_output_iterator()).first;
  }

  template<typename Graph, typename OutputIterator, typename VertexIndexMap>
  OutputIterator
  articulation_points(const Graph& g, OutputIterator out,
                      VertexIndexMap index_map)
  {
    return biconnected_components(g, dummy_property_map(), out,
                                  index_map).second;
  }

  template<typename Graph, typename OutputIterator>
  OutputIterator
  articulation_points(const Graph& g, OutputIterator out)
  {
    return biconnected_components(g, dummy_property_map(), out,
                                  get(vertex_index, g)).second;
  }

}                               // namespace boost

#endif  /* BOOST_GRAPH_BICONNECTED_COMPONENTS_HPP */


/* FILE: common.cc
 *
 * Common code for doubledouble.cc and alt_doubledouble.cc.
 *
 * NOTICE: Please see the file ../../LICENSE
 *
 */

#include <assert.h>
#include "xpcommon.h"

#if XP_USE_FLOAT_TYPE == XP_MPFR_TYPE
#include <boost/math/special_functions/fpclassify.hpp>
#include <boost/math/special_functions/sign.hpp>
using boost::math::isfinite;
using boost::math::signbit;
#endif

/* End includes */

////////////////////////////////////////////////////////////////////////
/// Start value safe block (associative floating point optimization
/// disallowed).
////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////
// Extended value support (infinities, NaNs):
//
// The are a host of various isnan, isinf, isfinite, which are
// non-standard and broken in various ingenious ways on different
// compilers with different compiler options.  But mostly what is
// needed in this source file is a check on whether or not a given
// value is finite.  The following test appears pretty robust:
#if XP_USE_FLOAT_TYPE == XP_MPFR_TYPE
// MPFR type doesn't support volatile qualifier, so
// use standard C++11 library routines
OC_BOOL Xp_IsFinite(XP_DDFLOAT_TYPE tx)
{ return isfinite(tx); }
OC_BOOL Xp_IsPosInf(XP_DDFLOAT_TYPE tx)
{ return (tx == XP_INFINITY); }
OC_BOOL Xp_IsNegInf(XP_DDFLOAT_TYPE tx)
{ return (tx == -XP_INFINITY); }

#else // !XP_USE_FLOAT_TYPE == XP_MPFR_TYPE

OC_BOOL Xp_IsFinite(XP_DDFLOAT_TYPE tx)
{
  volatile XP_DDFLOAT_TYPE x = tx;
  return (-XP_DDFLOAT_MAX<=x && x<=XP_DDFLOAT_MAX);
}
OC_BOOL Xp_IsPosInf(XP_DDFLOAT_TYPE tx)
{ // Depending on compiler flags, differentiating Infs from NaNs is
  // difficult.  The following is a best try:
  volatile XP_DDFLOAT_TYPE x = tx;
  if(x == XP_INFINITY && !(x == -XP_INFINITY)) return 1;
  return 0;
  /// A more robust though probably slower alternative would be
  /// return (memcmp(&x,&XP_INFINITY,sizeof(x))==0);
}
OC_BOOL Xp_IsNegInf(XP_DDFLOAT_TYPE tx)
{ // Depending on compiler flags, differentiating Infs from NaNs is
  // difficult.  The following is a best try:
  volatile XP_DDFLOAT_TYPE x = tx;
  if(x == -XP_INFINITY && !(x == XP_INFINITY)) return 1;
  return 0;
  /// A more robust though probably slower alternative would be
  ///    XP_DDFLOAT_TYPE chk = -XP_INFINITY;
  ///    return (memcmp(&x,&chk,sizeof(x))==0);
}
#endif // XP_USE_FLOAT_TYPE == XP_MPFR_TYPE

OC_BOOL Xp_IsNaN(XP_DDFLOAT_TYPE x)
{
  if(Xp_IsFinite(x) || Xp_IsPosInf(x) || Xp_IsNegInf(x)) {
    return 0;
  }
  return 1;
}

// Some compilers (e.g. g++ 5.3.1) will take code like this
//
//    if(x==0.0) {
//       signbit = Xp_SignBit(x)
//    }
//
// and replace it with
//
//    if(x==0.0) {
//       signbit = Xp_SignBit(0.0)
//    }
//
// which is a broken optimization if one wants to distinguish between x
// being +0.0 and -0.0.  A workaround is to use a non-inlined subroutine
// call to make the magnitude check, e.g.
//
//    if(Xp_IsZero(x)) {
//       signbit = Xp_SignBit(0.0)
//    }
//
// (Here if(fabs(x)==0.0) might also work, depending on how much the
// compiler knows about fabs().)  The Xp_AreEqual routine handles
// similar issues for comparisons between two values.
//
// These routines also take care of NaN handling problems.
OC_BOOL Xp_IsZero(XP_DDFLOAT_TYPE x)
{
  return (Xp_IsFinite(x) && 0.0 == x);
}
OC_BOOL Xp_AreEqual(XP_DDFLOAT_TYPE x,XP_DDFLOAT_TYPE y)
{
  if(Xp_IsNaN(x) || Xp_IsNaN(y)) return 0;
  return (x == y);
}

// The Xp_SignBit routines return 1 if x is negative, 0 if positive
// (same as std::signbit spec).
#if XP_USE_FLOAT_TYPE == XP_MPFR_TYPE
OC_BOOL Xp_SignBit(XP_DDFLOAT_TYPE x)
{ return boost::math::signbit(x); }
#else // !XP_USE_FLOAT_TYPE == XP_MPFR_TYPE
OC_BOOL Xp_SignBit(OC_REAL4 x)
{
  union BITS {
    OC_REAL4 f;
    OC_UINT4 u;
  };
  BITS a = {1.0};
  BITS b = {-1.0};
  BITS c = { x };
  if((a.u ^ b.u) & c.u) return 1;
  return 0;
}
OC_BOOL Xp_SignBit(OC_REAL8 x)
{
  union BITS {
    OC_REAL8 f;
    OC_UINT8 u;
  };
  BITS a = {1.0};
  BITS b = {-1.0};
  BITS c = { x };
  if((a.u ^ b.u) & c.u) return 1;
  return 0;
}
OC_BOOL Xp_SignBit(long double x)
{ // This code could be sped up considerably, in particular
  // by determining a priori the one bit where 1.0 and -1.0
  // differ, and then checking just that one bit.
  assert(sizeof(long double) % sizeof(unsigned int) == 0);
  static const long double af =  1.0;
  static const long double bf = -1.0;
  unsigned int const * a = reinterpret_cast<unsigned int const *>(&af);
  unsigned int const * b = reinterpret_cast<unsigned int const *>(&bf);
  unsigned int const * c = reinterpret_cast<unsigned int const *>(&x);
  for(size_t i=0; i*sizeof(unsigned int)<sizeof(long double); ++i) {
    if((a[i] ^ b[i]) & c[i]) return 1;
  }
  return 0;
}
#endif // XP_USE_FLOAT_TYPE == XP_MPFR_TYPE

////////////////////////////////////////////////////////////////////////
/// End value safe block
////////////////////////////////////////////////////////////////////////

int HexFloatWidth()
{
  return (XP_DDFLOAT_MANTISSA_PRECISION+6)/4
    + 6 + (XP_DDFLOAT_HUGE_EXP<3000 ? 4 : 5);
}

std::string HexFloatFormat(XP_DDFLOAT_TYPE value)
{
  char buf[256+XP_DDFLOAT_MANTISSA_PRECISION/4];
  if(!Xp_IsFinite(value)) { // Use %g to decide how to print the value
    snprintf(buf,sizeof(buf),"%g",static_cast<double>(value));
    char* cptr=buf;
    while(*cptr != '\0') {
      *cptr = static_cast<char>(tolower(*cptr));
      ++cptr;
    }
    std::string str = buf;
    if(str.find("inf")== std::string::npos) {
      str = "NaN";
    } else {
      if(str[0]=='-') {
        str = "-Inf";
      } else {
        str = "Inf";
      }
    }
    return str;
  }

  char* cptr = buf;
  XP_DDFLOAT_TYPE mantissa;
  int exp;
  mantissa = XP_FREXP(value,&exp);
  if(!Xp_SignBit(value)) { // Xp_SignBit detects signed zero
    *(cptr++) = ' ';  // Leave sign space
  } else {
    *(cptr++) = '-';
    mantissa *= -1;
  }

  // Write "0x" prefix to mantissa string, and leading "1."
  *(cptr++) = '0';  *(cptr++) = 'x';
  if(mantissa == 0.0) {
    *(cptr++) = '0';
  } else {
    *(cptr++) = '1';
    mantissa = 2*mantissa - 1.0;
    exp -= 1;
  }
  *(cptr++) = '.';

  // Write mantissa as hex digits
  for(int offset=1; offset<XP_DDFLOAT_MANTISSA_PRECISION; offset+=4) {
    mantissa *= 16;
    XP_DDFLOAT_TYPE fval = floor(mantissa);
    int ival = static_cast<int>(fval); // i.e., floor(mantissa)
    /// MPFR library has some trouble taking int() on temporary.
    if(ival<10) *(cptr++) = static_cast<char>('0' + ival);
    else        *(cptr++) = static_cast<char>('A' + ival - 10);
    mantissa -= ival;
  }

  if(XP_DDFLOAT_HUGE_EXP<3000) {
    snprintf(cptr,sizeof(buf)-(cptr-buf),"p%+05d",exp);
  } else {
    snprintf(cptr,sizeof(buf)-(cptr-buf),"p%+06d",exp);
  }
  return std::string(buf);
}

XP_DDFLOAT_TYPE ReadOneHexFloat(const char* buf,const char*& remainder)
{
  const int MAXSTOP = 16384; // Maximum buf size; fallback stop
  const char* CSTOP = buf + MAXSTOP;
  // Skip to data start; data has form 0x*, Inf, or NaN
  const char* cptr = strpbrk(buf,"0iInN");
  if(cptr == 0) { // No data
    remainder = 0;
    return 0.0;
  }
  // Check sign
  XP_DDFLOAT_TYPE valsign = 1.0;
  if( cptr - buf > 0 && *(cptr-1) == '-') {
    valsign = -1.0;
  }

  // Check for special values
  if(tolower(cptr[0])=='i' && tolower(cptr[1])=='n'
     && tolower(cptr[2])=='f') { // Infinity
    remainder = cptr+3;
    return valsign*XP_INFINITY;
  }
  if(tolower(cptr[0])=='n' && tolower(cptr[1])=='a'
     && tolower(cptr[2])=='n') { // NaN
    remainder = cptr+3;
    return XP_NAN;
  }

  // Otherwise, cptr should be pointing at a standard hexfloat.
  // First, convert string up to "."  Should be at most one digit.
  // (Moreover, that digit is suppose to be "1".)
  char* endptr;
  XP_DDFLOAT_TYPE val = XP_DDFLOAT_TYPE(strtol(cptr+2,&endptr,16));
  if(*endptr != '.') {
    std::string msg = "Bad input to ReadOneHexFloat: " + std::string(buf);
    throw msg;
  }
  cptr = endptr+1;
  XP_DDFLOAT_TYPE scale = 1.0/16.0;
  while(*cptr != 'p' && *cptr != '\0' && cptr != CSTOP) {
    int ival = *cptr - '0';
    if(ival>9) {
      ival -= ('A' - '0');
      if(ival>5) ival -= ('a'-'A');
      ival += 10;
    }
    val += XP_DDFLOAT_TYPE(ival)*scale;
    scale *= 1.0/16.0;
    // One alternative is to parse from back to front using a Horner
    // type algorithm to scale and sum values.
    ++cptr;
  }
  if(*cptr == 'p' || *cptr == 'P') {
    // Read exponent
    int iexp = strtol(cptr+1,&endptr,10);
    // Many implementations of ldexp misbehave in underflow
    // situations, by either flushing to zero or not rounding
    // properly.  This is not a critical path, so just brute-force it:
    if(iexp>0) {
      for(int i=0;i<iexp;++i) val *= 2;
    } else if(iexp<0) {
      for(int i=0;i>iexp;--i) val *= 0.5;
    }
    cptr = endptr;
  }

  remainder = cptr;
  return valsign*val;
}

int HexBinaryFloatWidth()
{
  return (XP_DDFLOAT_MANTISSA_PRECISION+3)/4
    + 6 + (XP_DDFLOAT_HUGE_EXP<3000 ? 3 : 4);
}

std::string HexBinaryFloatFormat(XP_DDFLOAT_TYPE value)
{
  char buf[256+XP_DDFLOAT_MANTISSA_PRECISION/4];

  if(!Xp_IsFinite(value)) { // Use %g to decide how to print the value
    snprintf(buf,sizeof(buf),"%g",static_cast<double>(value));
    char* cptr=buf;
    while(*cptr != '\0') {
      *cptr = static_cast<char>(tolower(*cptr));
      ++cptr;
    }
    std::string str = buf;
    if(str.find("inf")== std::string::npos) {
      str = "NaN";
    } else {
      if(str[0]=='-') {
        str = "-Inf";
      } else {
        str = "Inf";
      }
    }
    return str;
  }

  char* cptr = buf;
  XP_DDFLOAT_TYPE mantissa;
  int exp;
  mantissa = XP_FREXP(value,&exp);
  if(!Xp_SignBit(value)) { // Xp_SignBit detects signed zero
    *(cptr++) = ' ';  // Leave sign space
  } else {
    *(cptr++) = '-';
    mantissa *= -1;
  }

  // Write "0x" prefix to mantissa string
  *(cptr++) = '0';
  *(cptr++) = 'x';

  // Lead shift; if precision is not divisible by 4, then write
  // "left-over" bits (which won't fill a full hex digit) first.
#if XP_DDFLOAT_MANTISSA_PRECISION%4 != 0
    mantissa *= pow(XP_DDFLOAT_TYPE(2.0),XP_DDFLOAT_MANTISSA_PRECISION%4);
    exp -= XP_DDFLOAT_MANTISSA_PRECISION%4;
#else
    mantissa *= 16;
    exp -= 4;
#endif

  // Write mantissa as hex digits
  for(int offset=0; 4*offset<XP_DDFLOAT_MANTISSA_PRECISION; ++offset) {
    XP_DDFLOAT_TYPE fval = floor(mantissa);
    int ival = static_cast<int>(fval); // i.e., floor(mantissa)
    /// MPFR library has some trouble taking int() on temporary.
    if(ival<10) *(cptr++) = static_cast<char>('0' + ival);
    else        *(cptr++) = static_cast<char>('A' + ival - 10);
    mantissa -= ival;
    mantissa *= 16;
    exp -= 4;
  }

  exp += 4;
  if(XP_DDFLOAT_HUGE_EXP<3000) {
    snprintf(cptr,sizeof(buf)-(cptr-buf),"xb%+04d",exp);
  } else {
    snprintf(cptr,sizeof(buf)-(cptr-buf),"xb%+05d",exp);
  }
  return std::string(buf);
}

XP_DDFLOAT_TYPE ScanHexBinFloat(const char* cptr)
{ // Support for HexHex-Float and HexBin-Float formats, which have form
  //
  //    smmm...mmmxseee         (HexHex-Float)
  //    smmm...mmmxbseee        (HexBin-Float)
  //
  // where s is an optional mantisa sign (+ or -), mmm...mmm is an
  // arbitrary length run of hexadecimal digits (0-9, a-f, A-F), followed
  // by a literal 'x' (or 'X') or 'xb' (or 'XB') indicating the base of
  // the exponent (16 or 2, respectively), followed by an optional
  // exponent sign, and then a run of decimal digits representing the
  // power of 16 or 2.  Examples of the HexHex-Float format:
  //
  //     5a0x3
  //
  // is the decimal number (5*16^2 + 10*16) * 16^3 = 1440 * 4096 = 5898240.
  // and
  //      120Fx-7
  //
  // is the decimal number (1*16^3 + 2*16^2 + 15) * 16^-7 = 4623/268435456
  //                                      = 0.0000172220170497894287109375
  //
  // Examples of the HexBin-format:
  //
  //     5a0xb3
  //
  // is the decimal number (5*16^2 + 10*16) * 2^3 = 1440 * 8 = 11520.
  // and
  //      120Fxb-7
  //
  // is the decimal number (1*16^3 + 2*16^2 + 15) * 2^-7 = 4623/128
  //                                                     = 36.1171875
  //
  // Note: C99 and C++11 specify a different hexfloat format, represented
  // by the format specifier %a.  See the ScanC99HexFloat routine for
  // details.

  // Safer to work with unsigned chars
  const unsigned char* ptr = (const unsigned char*)cptr;

  // Skip leading junk
  unsigned char ch;
  while((ch=*ptr) != 0x0 && ch!='+' && ch!='-' &&
        !(('0'<=ch && ch<='9')                                  \
          || ('a'<=ch && ch<='f') || ('A'<=ch && ch<='F'))) {
    ++ptr;
  }
  // Set sign on mantissa
  int sign = 1;
  if(ch=='-') {
    sign = -1;
    ch = *(++ptr);
  } else if(ch=='+') {
    ch = *(++ptr);
  }

  // Skip leading "0x", if any
  if(ch == '0') {
    ch = *(++ptr);
    if(ch == 'x' || ch == 'X') {
      ch = *(++ptr);
    }
  }

  // Read mantissa
  XP_DDFLOAT_TYPE value = 0.0;
  while(ch != 0x0) {
    unsigned int digit;
    if(ch=='-') {
      sign = -1;
    } else if(ch=='+') {
      sign = 1;
    } else {
      if('0'<=ch && ch<='9') {
        digit = static_cast<unsigned int>(ch - '0');
      } else if('a'<=ch && ch<='f') {
        digit = static_cast<unsigned int>(ch - 'a' + 10);
      } else if('A'<=ch && ch<='F') {
        digit = static_cast<unsigned int>(ch - 'A' + 10);
      } else { // Bad value
        break;
      }
      value = 16*value + digit;
    }
    ch=*(++ptr);
  }

  // Exponent
  int exponent=0;
  double base=16.;
  if(ch=='x' || ch=='X') {
    ch=*(++ptr);
    if(ch=='b' || ch=='B') {
      base=2.;
      ++ptr;
    }
    exponent = atoi((const char*)(ptr));
  }
  if(base == 16) {
    exponent *= 4;
  }

  // Put it all together.  Break exponent up as necessary to protect
  // against under/overflow.  This code also in ScanC99HexFloat().
  while(exponent > XP_DDFLOAT_HUGE_EXP-1) {
    value *= pow(XP_DDFLOAT_TYPE(2),XP_DDFLOAT_TYPE(XP_DDFLOAT_HUGE_EXP-1));
    exponent -= XP_DDFLOAT_HUGE_EXP-1;
  }
  while(exponent < XP_DDFLOAT_TINY_EXP+1) {
    value *= pow(XP_DDFLOAT_TYPE(2),XP_DDFLOAT_TYPE(XP_DDFLOAT_TINY_EXP+1));
    exponent -= XP_DDFLOAT_TINY_EXP+1;
  }
  value *= pow(XP_DDFLOAT_TYPE(2),XP_DDFLOAT_TYPE(exponent));

  return sign*value;
}

XP_DDFLOAT_TYPE ScanC99HexFloat(const char* cptr)
{ // The format for the C99/C++11 hexfloat format is
  //    sOx1.mmm...mmmpseee         (hexfloat)
  // where s is an optional mantisa sign (+ or -), 0x is a literal
  // identifier indicating a hexadecimal value, 1. is the first part of
  // the normalized hexadecimal floating point value. mmm...mmm is an
  // arbitrary length run of hexadecimal digits (0-9, a-f, A-F),
  // followed by a literal 'p' (or 'P') indicating the start of the
  // base-2 exponent, then an optional exponent sign, and then a run of
  // decimal digits representing the power of 2.  Examples of the C99
  // hexfloat format:
  //
  //     0x1.68p13
  //
  // is the decimal number (1+6/16+8/16^2) * 2^13 = (360/256) * 2^13
  // = 360 * 2^5= 11520, and
  //
  //    -0x1.20Fp+5
  //
  // is the decimal number -(1*16^3 + 2*16^2 + 15) * 2^(5-12)
  // = -4623/128 = -36.1171875
  //
  // This is very similar to the HexBin format above, the difference
  // being the location of the hex point in the mantissa---this
  // shifts the exponent and re-jiggers the binary-to-hex grouping
  // in the mantissa.

  // Safer to work with unsigned chars
  const unsigned char* ptr = (const unsigned char*)cptr;

  // Skip leading junk
  unsigned char ch;
  while((ch=*ptr) != 0x0 && ch!='+' && ch!='-' &&
        !(('0'<=ch && ch<='9')                                  \
          || ('a'<=ch && ch<='f') || ('A'<=ch && ch<='F'))) {
    ++ptr;
  }
  // Set sign on mantissa
  int sign = 1;
  if(ch=='-') {
    sign = -1;
    ch = *(++ptr);
  } else if(ch=='+') {
    ch = *(++ptr);
  }

  // Skip leading "0x", if any
  if(ch == '0') {
    ch = *(++ptr);
    if(ch == 'x' || ch == 'X') {
      ch = *(++ptr);
    }
  }

  // Next two characters should be "1." or "0.", the latter only on
  // zero input.
  if(ch == '0') {
    // Optimization bugs will sometimes drop sign on sign*0.0, so use
    // copysign instead.
#if XP_HAVE_COPYSIGN
    return copysign(static_cast<XP_DDFLOAT_TYPE>(0.0),
                    static_cast<XP_DDFLOAT_TYPE>(sign));
#else
    return sign*static_cast<XP_DDFLOAT_TYPE>(0.0);
#endif
  }
  if(ch != '1' || *(++ptr) != '.') {
    std::string errmsg
      = "Error in ScanC99HexFloat; Invalid C99 hexfloat string: ";
    errmsg += cptr;
    throw errmsg;
  }

  // Read mantissa
  XP_DDFLOAT_TYPE value = 1.0;
  int exponent = 0;
  while( (ch = *(++ptr)) != 0x0) {
    unsigned int digit;
    if('0'<=ch && ch<='9') {
      digit = static_cast<unsigned int>(ch - '0');
    } else if('a'<=ch && ch<='f') {
      digit = static_cast<unsigned int>(ch - 'a' + 10);
    } else if('A'<=ch && ch<='F') {
      digit = static_cast<unsigned int>(ch - 'A' + 10);
    } else { // Bad value
      break;
    }
    value = 16*value + digit;
    exponent -= 4;
  }

  // Exponent (base is 2)
  if(ch=='p' || ch=='P') {
    exponent += atoi((const char*)(++ptr));
  }

  // Put it all together.  Break exponent up as necessary to protect
  // against under/overflow.  This code also in ScanHexBinFloat().
  while(exponent > XP_DDFLOAT_HUGE_EXP-1) {
    value *= pow(XP_DDFLOAT_TYPE(2),XP_DDFLOAT_TYPE(XP_DDFLOAT_HUGE_EXP-1));
    exponent -= XP_DDFLOAT_HUGE_EXP-1;
  }
  while(exponent < XP_DDFLOAT_TINY_EXP+1) {
    value *= pow(XP_DDFLOAT_TYPE(2),XP_DDFLOAT_TYPE(XP_DDFLOAT_TINY_EXP+1));
    exponent -= XP_DDFLOAT_TINY_EXP+1;
  }
  value *= pow(XP_DDFLOAT_TYPE(2),XP_DDFLOAT_TYPE(exponent));

  return sign*value;
}

XP_DDFLOAT_TYPE ScanFloat(const char* cptr)
{
  // If string contains an p or P, then calls ScanC99HexFloat.
  // If string contains an x or X, then calls ScanHexBinFloat.
  // Otherwise uses strtold()
  // Note: Check for 'p' first since C99HexFloat also contains
  //       an 'x' in the '0x' prefix.
  XP_DDFLOAT_TYPE value;
  // First check for infinities and NaNs.
  const char* special = strstr(cptr,"Inf");
  if(special) {
    XP_DDFLOAT_TYPE value_sign = 1;
    if(special>cptr && *(special-1) == '-') {
      value_sign = -1;
    }
    return value_sign*XP_INFINITY;
  }
  if(strstr(cptr,"NaN")) {
    return XP_NAN;
  }

  // Else, determine string format and process accordingly.
  if(strchr(cptr,'p') || strchr(cptr,'P')) {
    // Assume C99 hex-float
    value = ScanC99HexFloat(cptr);
  } else if(strchr(cptr,'x') || strchr(cptr,'X')) {
    // Assume hexhex-float
    value = ScanHexBinFloat(cptr);
  } else {
    // Assume decimal float
    value = static_cast<XP_DDFLOAT_TYPE>(strtold(cptr,0));
  }

  return value;
}