//==============================================================================
//         Copyright 2003 - 2011 LASMEA UMR 6602 CNRS/Univ. Clermont II
//         Copyright 2009 - 2011 LRI    UMR 8623 CNRS/Univ Paris Sud XI
//         Copyright 2012 - 2014 MetaScale SAS
//
//          Distributed under the Boost Software License, Version 1.0.
//                 See accompanying file LICENSE.txt or copy at
//                     http://www.boost.org/LICENSE_1_0.txt
//==============================================================================
#ifndef BOOST_SIMD_IEEE_FUNCTIONS_SIMD_COMMON_FAST_FREXP_HPP_INCLUDED
#define BOOST_SIMD_IEEE_FUNCTIONS_SIMD_COMMON_FAST_FREXP_HPP_INCLUDED

#include <boost/simd/ieee/functions/frexp.hpp>
#include <boost/simd/include/functions/simd/bitwise_cast.hpp>
#include <boost/simd/include/functions/simd/bitwise_and.hpp>
#include <boost/simd/include/functions/simd/bitwise_or.hpp>
#include <boost/simd/include/functions/simd/bitwise_andnot.hpp>
#include <boost/simd/include/functions/simd/shr.hpp>
#include <boost/simd/include/functions/simd/minus.hpp>
#include <boost/simd/include/constants/maxexponentm1.hpp>
#include <boost/simd/include/constants/mask1frexp.hpp>
#include <boost/simd/include/constants/mask2frexp.hpp>
#include <boost/simd/include/constants/nbmantissabits.hpp>
#include <boost/simd/sdk/meta/scalar_of.hpp>
#include <boost/dispatch/meta/as_integer.hpp>
#include <boost/dispatch/attributes.hpp>
#include <boost/fusion/include/std_pair.hpp>
#include <boost/type_traits/is_same.hpp>

namespace boost { namespace simd { namespace ext
{
  BOOST_DISPATCH_IMPLEMENT_IF          ( fast_frexp_
                                       , tag::cpu_
                                       , (A0)(A1)(X)(Y)
                                       , ( boost::is_same
                                           < typename  dispatch::meta
                                                       ::as_integer<A0>::type
                                           , A1
                                           >
                                         )
                                       , ((simd_< floating_<A0>, X>))
                                         ((simd_< floating_<A0>, X>))
                                         ((simd_< integer_<A1>, Y>))
                                       )
  {
    typedef void result_type;

    BOOST_FORCEINLINE result_type operator()(A0 const& a0,A0 & r0,A1 & r1) const
    {
      typedef typename dispatch::meta::as_integer<A0, signed>::type int_type;
      typedef typename meta::scalar_of<A0>::type                      s_type;

      r1  = simd::bitwise_cast<int_type>(b_and(Mask1frexp<A0>(), a0));
      A0  x = b_andnot(a0, Mask1frexp<A0>());
      r1  = shr(r1,Nbmantissabits<s_type>()) - Maxexponentm1<A0>();
      r0  = b_or(x,Mask2frexp<A0>());
    }
  };

  BOOST_DISPATCH_IMPLEMENT_IF          ( fast_frexp_, tag::cpu_
                                       , (A0)(A1)(X)(Y)
                                       , ( boost::is_same
                                           < typename  dispatch::meta
                                                       ::as_integer<A0>::type
                                           , A1
                                           >
                                         )
                                       , ((simd_< floating_<A0>, X>))
                                         ((simd_< integer_<A1>, Y>))
                                       )
  {
    typedef A0 result_type;
    BOOST_FORCEINLINE A0 operator()(A0 const& a0,A1 & a2) const
    {
      A0 a1;
      boost::simd::fast_frexp(a0, a1, a2);
      return a1;
    }
  };

  BOOST_DISPATCH_IMPLEMENT          ( fast_frexp_, tag::cpu_
                                    , (A0)(X)
                                    , ((simd_<arithmetic_<A0>,X>))
                                    )
  {
    typedef typename dispatch::meta::as_integer<A0, signed>::type exponent;
    typedef std::pair<A0,exponent>                                result_type;

    BOOST_FORCEINLINE result_type operator()(A0 const& a0) const
    {
      A0 first;
      exponent second;
      boost::simd::fast_frexp(a0, first, second);
      return result_type(first, second);
    }
  };

} } }

#endif


///////////////////////////////////////////////////////////////////
//  Copyright Christopher Kormanyos 2019 - 2022.                 //
//  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 UINTWIDE_T_BACKEND_2019_12_15_HPP // NOLINT(llvm-header-guard)
  #define UINTWIDE_T_BACKEND_2019_12_15_HPP

  #include <cstdint>
  #include <limits>
  #include <string>
  #include <type_traits>
  #include <utility>
  #include <vector>

  #include <boost/version.hpp>

  #if !defined(BOOST_VERSION)
  #error BOOST_VERSION is not defined. Ensure that <boost/version.hpp> is properly included.
  #endif

  #if ((BOOST_VERSION >= 107900) && !defined(BOOST_MP_STANDALONE))
  #define BOOST_MP_STANDALONE
  #endif

  #if (BOOST_VERSION < 108000)
  #if defined(__GNUC__)
  #pragma GCC diagnostic push
  #pragma GCC diagnostic ignored "-Wconversion"
  #pragma GCC diagnostic push
  #pragma GCC diagnostic ignored "-Wsign-conversion"
  #pragma GCC diagnostic push
  #pragma GCC diagnostic ignored "-Wunused-parameter"
  #endif
  #endif

  #if (defined(__GNUC__) && !defined(__clang__) && (__GNUC__ >= 12))
  #pragma GCC diagnostic push
  #pragma GCC diagnostic ignored "-Wrestrict"
  #endif

  #if (BOOST_VERSION < 108000)
  #if (defined(__clang__) && (__clang_major__ > 9)) && !defined(__APPLE__)
  #pragma GCC diagnostic push
  #pragma GCC diagnostic ignored "-Wdeprecated-copy"
  #endif
  #endif

  #if (BOOST_VERSION < 107900)
  #include <boost/config.hpp>
  #endif
  #include <boost/multiprecision/number.hpp>

  #include <math/wide_integer/uintwide_t.h>

  #if(__cplusplus >= 201703L)
  namespace boost::multiprecision {
  #else
  namespace boost { namespace multiprecision { // NOLINT(modernize-concat-nested-namespaces)
  #endif

  // Forward declaration of the uintwide_t_backend multiple precision class.
  // This class binds native (WIDE_INTEGER_NAMESPACE)::math::wide_integer::uintwide_t
  // to boost::multiprecsion::uintwide_t_backend.
  template<
  #if defined(WIDE_INTEGER_NAMESPACE)
           const WIDE_INTEGER_NAMESPACE::math::wide_integer::size_t MyWidth2,
  #else
           const ::math::wide_integer::size_t MyWidth2,
  #endif
           typename MyLimbType = std::uint32_t,
           typename MyAllocatorType = void>
  class uintwide_t_backend;

  // Define the number category as an integer number kind
  // for the uintwide_t_backend. This is needed for properly
  // interacting as a backend with boost::muliprecision.
  #if (BOOST_VERSION <= 107200)
  template<
  #if defined(WIDE_INTEGER_NAMESPACE)
           const WIDE_INTEGER_NAMESPACE::math::wide_integer::size_t MyWidth2,
  #else
           const ::math::wide_integer::size_t MyWidth2,
  #endif
           typename MyLimbType,
           typename MyAllocatorType>
  struct number_category<uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>>
    : public boost::mpl::int_<number_kind_integer> { };
  #elif (BOOST_VERSION <= 107500)
  template<
  #if defined(WIDE_INTEGER_NAMESPACE)
           const WIDE_INTEGER_NAMESPACE::math::wide_integer::size_t MyWidth2,
  #else
           const ::math::wide_integer::size_t MyWidth2,
  #endif
           typename MyLimbType,
           typename MyAllocatorType>
  struct number_category<uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>>
    : public boost::integral_constant<unsigned int, number_kind_integer> { };
  #else
  template<
  #if defined(WIDE_INTEGER_NAMESPACE)
           const WIDE_INTEGER_NAMESPACE::math::wide_integer::size_t MyWidth2,
  #else
           const ::math::wide_integer::size_t MyWidth2,
  #endif
           typename MyLimbType,
           typename MyAllocatorType>
  struct number_category<uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>>
    : public std::integral_constant<unsigned int, number_kind_integer> { };
  #endif

  // This is the uintwide_t_backend multiple precision class.
  template<
  #if defined(WIDE_INTEGER_NAMESPACE)
           const WIDE_INTEGER_NAMESPACE::math::wide_integer::size_t MyWidth2,
  #else
           const ::math::wide_integer::size_t MyWidth2,
  #endif
           typename MyLimbType,
           typename MyAllocatorType>
  class uintwide_t_backend // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
  {
  public:
    using representation_type =
    #if defined(WIDE_INTEGER_NAMESPACE)
      WIDE_INTEGER_NAMESPACE::math::wide_integer::uintwide_t<MyWidth2, MyLimbType, MyAllocatorType>;
    #else
      ::math::wide_integer::uintwide_t<MyWidth2, MyLimbType, MyAllocatorType>;
    #endif

    #if (BOOST_VERSION <= 107500)
    using signed_types   = mpl::list<std::int64_t>;
    using unsigned_types = mpl::list<std::uint64_t>;
    using float_types    = mpl::list<long double>;
    #else
    using   signed_types = std::tuple<  signed char,   signed short,   signed int,   signed long,   signed long long, std::intmax_t>;  // NOLINT(google-runtime-int)
    using unsigned_types = std::tuple<unsigned char, unsigned short, unsigned int, unsigned long, unsigned long long, std::uintmax_t>; // NOLINT(google-runtime-int)
    using float_types    = std::tuple<float, double, long double>;
    #endif

    constexpr uintwide_t_backend() : m_value() { }

    explicit constexpr uintwide_t_backend(const representation_type& rep)
      : m_value(std::move(rep)) { }

    constexpr uintwide_t_backend(const uintwide_t_backend& other) : m_value(other.m_value) { }

    constexpr uintwide_t_backend(uintwide_t_backend&& other) noexcept
      : m_value(static_cast<representation_type&&>(other.m_value)) { }

    template<typename UnsignedIntegralType,
             std::enable_if_t<(   (std::is_integral<UnsignedIntegralType>::value)
                               && (std::is_unsigned<UnsignedIntegralType>::value))> const* = nullptr>
    constexpr uintwide_t_backend(UnsignedIntegralType u) : m_value(representation_type(std::uint64_t(u))) { } // NOLINT(google-explicit-constructor,hicpp-explicit-conversions)

    template<typename SignedIntegralType,
             std::enable_if_t<(   (std::is_integral<SignedIntegralType>::value)
                               && (std::is_signed  <SignedIntegralType>::value))> const* = nullptr>
    constexpr uintwide_t_backend(SignedIntegralType n) : m_value(representation_type(std::int64_t(n))) { } // NOLINT(google-explicit-constructor,hicpp-explicit-conversions)

    template<typename FloatingPointType,
             std::enable_if_t<std::is_floating_point<FloatingPointType>::value> const* = nullptr>
    constexpr uintwide_t_backend(FloatingPointType f) : m_value(representation_type(static_cast<long double>(f))) { } // NOLINT(google-explicit-constructor,hicpp-explicit-conversions)

    constexpr uintwide_t_backend(const char* c) : m_value(c) { } // NOLINT(google-explicit-constructor,hicpp-explicit-conversions)

    constexpr uintwide_t_backend(const std::string& str) : m_value(str) { } // NOLINT(google-explicit-constructor,hicpp-explicit-conversions)

    WIDE_INTEGER_CONSTEXPR ~uintwide_t_backend() = default;

    WIDE_INTEGER_CONSTEXPR auto operator=(const uintwide_t_backend& other) -> uintwide_t_backend& // NOLINT(cert-oop54-cpp)
    {
      if(this != &other)
      {
        m_value.representation() = other.m_value.crepresentation();
      }

      return *this;
    }

    WIDE_INTEGER_CONSTEXPR auto operator=(uintwide_t_backend&& other) noexcept -> uintwide_t_backend&
    {
      m_value = static_cast<representation_type&&>(other.m_value);

      return *this;
    }

    template<typename ArithmeticType,
             std::enable_if_t<std::is_arithmetic<ArithmeticType>::value> const* = nullptr>
    WIDE_INTEGER_CONSTEXPR auto operator=(const ArithmeticType& x) -> uintwide_t_backend&
    {
      m_value = representation_type(x);

      return *this;
    }

    WIDE_INTEGER_CONSTEXPR auto operator=(const std::string& str_rep)  -> uintwide_t_backend& { m_value = representation_type(str_rep);  return *this; }
    WIDE_INTEGER_CONSTEXPR auto operator=(const char*        char_ptr) -> uintwide_t_backend& { m_value = representation_type(char_ptr); return *this; }

    WIDE_INTEGER_CONSTEXPR auto swap(uintwide_t_backend& other) -> void
    {
      m_value.representation().swap(other.m_value.representation());
    }

    WIDE_INTEGER_CONSTEXPR auto swap(uintwide_t_backend&& other) noexcept -> void
    {
      auto tmp = std::move(m_value.representation());

      m_value.representation() = std::move(other.m_value.representation());

      other.m_value.representation() = std::move(tmp);
    }

                           WIDE_INTEGER_CONSTEXPR auto  representation()       ->       representation_type& { return m_value; }
    WIDE_INTEGER_NODISCARD WIDE_INTEGER_CONSTEXPR auto  representation() const -> const representation_type& { return m_value; }
    WIDE_INTEGER_NODISCARD WIDE_INTEGER_CONSTEXPR auto crepresentation() const -> const representation_type& { return m_value; }

    WIDE_INTEGER_NODISCARD auto str(std::streamsize number_of_digits, const std::ios::fmtflags format_flags) const -> std::string
    {
      static_cast<void>(number_of_digits);

      // Use simple vector dynamic memory here. When using uintwide_t as a
      // Boost.Multiprecision number backend, we assume vector is available.

      std::vector<char>
        pstr
        (
          static_cast<typename std::vector<char>::size_type>(representation_type::wr_string_max_buffer_size_dec)
        );

      const std::uint_fast8_t base_rep     = (((format_flags & std::ios::hex)       != 0) ? 16U : 10U);
      const bool              show_base    = ( (format_flags & std::ios::showbase)  != 0);
      const bool              show_pos     = ( (format_flags & std::ios::showpos)   != 0);
      const bool              is_uppercase = ( (format_flags & std::ios::uppercase) != 0);

      const bool wr_string_is_ok = m_value.wr_string(pstr.data(), base_rep, show_base, show_pos, is_uppercase);

      std::string str_result = (wr_string_is_ok ? std::string(pstr.data()) : std::string());

      return str_result;
    }

    WIDE_INTEGER_CONSTEXPR auto negate() -> void
    {
      m_value.negate();
    }

    WIDE_INTEGER_NODISCARD constexpr auto compare(const uintwide_t_backend& other_mp_cpp_backend) const -> int
    {
      return static_cast<int>(m_value.compare(other_mp_cpp_backend.crepresentation()));
    }

    template<typename ArithmeticType,
             std::enable_if_t<std::is_arithmetic<ArithmeticType>::value> const* = nullptr>
    WIDE_INTEGER_NODISCARD constexpr auto compare(ArithmeticType x) const -> int
    {
      return static_cast<int>(m_value.compare(representation_type(x)));
    }

    WIDE_INTEGER_NODISCARD WIDE_INTEGER_CONSTEXPR auto hash() const -> std::size_t
    {
      auto result = static_cast<std::size_t>(0U);

      #if (BOOST_VERSION < 107800)
      using boost::hash_combine;
      #else
      using boost::multiprecision::detail::hash_combine;
      #endif
      for(auto   i = static_cast<typename representation_type::representation_type::size_type>(0U);
                 i < crepresentation().crepresentation().size();
               ++i)
      {
        hash_combine(result, crepresentation().crepresentation()[i]);
      }

      return result;
    }

    auto operator=(const representation_type&) -> uintwide_t_backend& = delete;

  private:
    representation_type m_value; // NOLINT(readability-identifier-naming)
  };

  template<
  #if defined(WIDE_INTEGER_NAMESPACE)
           const WIDE_INTEGER_NAMESPACE::math::wide_integer::size_t MyWidth2,
  #else
           const ::math::wide_integer::size_t MyWidth2,
  #endif
           typename MyLimbType,
           typename MyAllocatorType>
  WIDE_INTEGER_CONSTEXPR auto eval_add(uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>& result, const uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>& x) -> void
  {
    result.representation() += x.crepresentation();
  }

  template<
  #if defined(WIDE_INTEGER_NAMESPACE)
           const WIDE_INTEGER_NAMESPACE::math::wide_integer::size_t MyWidth2,
  #else
           const ::math::wide_integer::size_t MyWidth2,
  #endif
           typename MyLimbType,
           typename MyAllocatorType>
  WIDE_INTEGER_CONSTEXPR auto eval_subtract(uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>& result, const uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>& x) -> void
  {
    result.representation() -= x.crepresentation();
  }

  template<
  #if defined(WIDE_INTEGER_NAMESPACE)
           const WIDE_INTEGER_NAMESPACE::math::wide_integer::size_t MyWidth2,
  #else
           const ::math::wide_integer::size_t MyWidth2,
  #endif
           typename MyLimbType,
           typename MyAllocatorType>
  WIDE_INTEGER_CONSTEXPR auto eval_multiply(uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>& result, const uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>& x) -> void
  {
    result.representation() *= x.crepresentation();
  }

  template<
  #if defined(WIDE_INTEGER_NAMESPACE)
           const WIDE_INTEGER_NAMESPACE::math::wide_integer::size_t MyWidth2,
  #else
           const ::math::wide_integer::size_t MyWidth2,
  #endif
           typename MyLimbType,
           typename MyAllocatorType,
           typename IntegralType,
           std::enable_if_t<(std::is_integral<IntegralType>::value)> const* = nullptr>
  WIDE_INTEGER_CONSTEXPR auto eval_multiply(uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>& result, const IntegralType& n) -> void
  {
    result.representation() *= n;
  }

  template<
  #if defined(WIDE_INTEGER_NAMESPACE)
           const WIDE_INTEGER_NAMESPACE::math::wide_integer::size_t MyWidth2,
  #else
           const ::math::wide_integer::size_t MyWidth2,
  #endif
           typename MyLimbType,
           typename MyAllocatorType>
  WIDE_INTEGER_CONSTEXPR auto eval_divide(uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>& result, const uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>& x) -> void
  {
    result.representation() /= x.crepresentation();
  }

  template<
  #if defined(WIDE_INTEGER_NAMESPACE)
           const WIDE_INTEGER_NAMESPACE::math::wide_integer::size_t MyWidth2,
  #else
           const ::math::wide_integer::size_t MyWidth2,
  #endif
           typename MyLimbType,
           typename MyAllocatorType,
           typename IntegralType,
           std::enable_if_t<(   (std::is_integral   <IntegralType>::value)
                             && (std::is_unsigned   <IntegralType>::value)
                             && (std::numeric_limits<IntegralType>::digits <= std::numeric_limits<MyLimbType>::digits))> const* = nullptr>
  WIDE_INTEGER_CONSTEXPR auto eval_divide(uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>& result, const IntegralType& n) -> void
  {
    using local_wide_integer_type = typename uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>::representation_type;

    using local_limb_type = typename local_wide_integer_type::limb_type;

    result.representation().eval_divide_by_single_limb(static_cast<local_limb_type>(n), 0U, nullptr);
  }

  template<
  #if defined(WIDE_INTEGER_NAMESPACE)
           const WIDE_INTEGER_NAMESPACE::math::wide_integer::size_t MyWidth2,
  #else
           const ::math::wide_integer::size_t MyWidth2,
  #endif
           typename MyLimbType,
           typename MyAllocatorType,
           typename IntegralType,
           std::enable_if_t<(   (std::is_integral   <IntegralType>::value)
                             && (std::is_unsigned   <IntegralType>::value)
                             && (std::numeric_limits<IntegralType>::digits) > std::numeric_limits<MyLimbType>::digits)> const* = nullptr>
  WIDE_INTEGER_CONSTEXPR auto eval_divide(uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>& result, const IntegralType& n) -> void
  {
    result.representation() /= n;
  }

  template<
  #if defined(WIDE_INTEGER_NAMESPACE)
           const WIDE_INTEGER_NAMESPACE::math::wide_integer::size_t MyWidth2,
  #else
           const ::math::wide_integer::size_t MyWidth2,
  #endif
           typename MyLimbType,
           typename MyAllocatorType>
  WIDE_INTEGER_CONSTEXPR auto eval_modulus(uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>& result, const uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>& x) -> void
  {
    result.representation() %= x.crepresentation();
  }

  template<
  #if defined(WIDE_INTEGER_NAMESPACE)
           const WIDE_INTEGER_NAMESPACE::math::wide_integer::size_t MyWidth2,
  #else
           const ::math::wide_integer::size_t MyWidth2,
  #endif
           typename MyLimbType,
           typename MyAllocatorType,
           typename IntegralType,
           std::enable_if_t<(   (std::is_integral   <IntegralType>::value)
                             && (std::is_unsigned   <IntegralType>::value)
                             && (std::numeric_limits<IntegralType>::digits <= std::numeric_limits<MyLimbType>::digits))> const* = nullptr>
  WIDE_INTEGER_CONSTEXPR auto eval_integer_modulus(uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>& x, const IntegralType& n) -> IntegralType
  {
    using local_wide_integer_type = typename uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>::representation_type;

    typename uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>::representation_type rem;

    local_wide_integer_type(x.crepresentation()).eval_divide_by_single_limb(n, 0U, &rem);

    return static_cast<IntegralType>(rem);
  }

  template<
  #if defined(WIDE_INTEGER_NAMESPACE)
           const WIDE_INTEGER_NAMESPACE::math::wide_integer::size_t MyWidth2,
  #else
           const ::math::wide_integer::size_t MyWidth2,
  #endif
           typename MyLimbType,
           typename MyAllocatorType,
           typename IntegralType,
           std::enable_if_t<(   (std::is_integral   <IntegralType>::value)
                             && (std::is_unsigned   <IntegralType>::value)
                             && (std::numeric_limits<IntegralType>::digits) > std::numeric_limits<MyLimbType>::digits)> const* = nullptr>
  WIDE_INTEGER_CONSTEXPR auto eval_integer_modulus(uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>& x, const IntegralType& n) -> IntegralType
  {
    const uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType> rem = x.crepresentation() % uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>(n);

    return static_cast<IntegralType>(rem);
  }

  template<
  #if defined(WIDE_INTEGER_NAMESPACE)
           const WIDE_INTEGER_NAMESPACE::math::wide_integer::size_t MyWidth2,
  #else
           const ::math::wide_integer::size_t MyWidth2,
  #endif
           typename MyLimbType,
           typename MyAllocatorType>
  WIDE_INTEGER_CONSTEXPR auto eval_bitwise_and(uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>& result, const uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>& x) -> void
  {
    result.representation() &= x.crepresentation();
  }

  template<
  #if defined(WIDE_INTEGER_NAMESPACE)
           const WIDE_INTEGER_NAMESPACE::math::wide_integer::size_t MyWidth2,
  #else
           const ::math::wide_integer::size_t MyWidth2,
  #endif
           typename MyLimbType,
           typename MyAllocatorType>
  WIDE_INTEGER_CONSTEXPR auto eval_bitwise_or(      uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>& result,
                                              const uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>& x) -> void
  {
    result.representation() |= x.crepresentation();
  }

  template<
  #if defined(WIDE_INTEGER_NAMESPACE)
           const WIDE_INTEGER_NAMESPACE::math::wide_integer::size_t MyWidth2,
  #else
           const ::math::wide_integer::size_t MyWidth2,
  #endif
           typename MyLimbType,
           typename MyAllocatorType>
  WIDE_INTEGER_CONSTEXPR auto eval_bitwise_xor(uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>& result, const uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>& x) -> void
  {
    result.representation() ^= x.crepresentation();
  }

  template<
  #if defined(WIDE_INTEGER_NAMESPACE)
           const WIDE_INTEGER_NAMESPACE::math::wide_integer::size_t MyWidth2,
  #else
           const ::math::wide_integer::size_t MyWidth2,
  #endif
           typename MyLimbType,
           typename MyAllocatorType>
  WIDE_INTEGER_CONSTEXPR auto eval_complement(      uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>& result,
                                              const uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>& x) -> void
  {
    using local_limb_array_type =
      typename uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>::representation_type::representation_type;

    using local_size_type = typename local_limb_array_type::size_type;

    for(auto   i = static_cast<local_size_type>(0U);
               i < result.crepresentation().crepresentation().size();
             ++i)
    {
      using local_value_type = typename local_limb_array_type::value_type;

      result.representation().representation()[i] =
        static_cast<local_value_type>
        (
          ~x.crepresentation().crepresentation()[i]
        );
    }
  }

  template<
  #if defined(WIDE_INTEGER_NAMESPACE)
           const WIDE_INTEGER_NAMESPACE::math::wide_integer::size_t MyWidth2,
  #else
           const ::math::wide_integer::size_t MyWidth2,
  #endif
           typename MyLimbType,
           typename MyAllocatorType>
  WIDE_INTEGER_CONSTEXPR auto eval_powm(      uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>& result,
                                        const uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>& b,
                                        const uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>& p,
                                        const uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>& m) -> void
  {
    result.representation() = powm(b.crepresentation(),
                                   p.crepresentation(),
                                   m.crepresentation());
  }

  template<
  #if defined(WIDE_INTEGER_NAMESPACE)
           const WIDE_INTEGER_NAMESPACE::math::wide_integer::size_t MyWidth2,
  #else
           const ::math::wide_integer::size_t MyWidth2,
  #endif
           typename MyLimbType,
           typename MyAllocatorType,
           typename OtherIntegralTypeM,
           std::enable_if_t<(std::is_integral<OtherIntegralTypeM>::value)> const* = nullptr>
  WIDE_INTEGER_CONSTEXPR auto eval_powm(      uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>& result,
                                        const uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>& b,
                                        const uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>& p,
                                        const OtherIntegralTypeM                                         m) -> void
  {
    result.representation() = powm(b.crepresentation(),
                                   p.crepresentation(),
                                   m);
  }

  template<
  #if defined(WIDE_INTEGER_NAMESPACE)
           const WIDE_INTEGER_NAMESPACE::math::wide_integer::size_t MyWidth2,
  #else
           const ::math::wide_integer::size_t MyWidth2,
  #endif
           typename MyLimbType,
           typename MyAllocatorType,
           typename OtherIntegralTypeP,
           std::enable_if_t<(std::is_integral<OtherIntegralTypeP>::value)> const* = nullptr>
  WIDE_INTEGER_CONSTEXPR auto eval_powm(      uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>& result,
                                        const uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>& b,
                                        const OtherIntegralTypeP                                         p,
                                        const uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>& m) -> void
  {
    result.representation() = powm(b.crepresentation(),
                                   p,
                                   m.crepresentation());
  }

  template<
  #if defined(WIDE_INTEGER_NAMESPACE)
           const WIDE_INTEGER_NAMESPACE::math::wide_integer::size_t MyWidth2,
  #else
           const ::math::wide_integer::size_t MyWidth2,
  #endif
           typename MyLimbType,
           typename MyAllocatorType,
           typename IntegralType,
           std::enable_if_t<(std::is_integral<IntegralType>::value)> const* = nullptr>
  WIDE_INTEGER_CONSTEXPR auto eval_left_shift(uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>& result, const IntegralType& n) -> void
  {
    result.representation() <<= n;
  }

  template<
  #if defined(WIDE_INTEGER_NAMESPACE)
           const WIDE_INTEGER_NAMESPACE::math::wide_integer::size_t MyWidth2,
  #else
           const ::math::wide_integer::size_t MyWidth2,
  #endif
           typename MyLimbType,
           typename MyAllocatorType,
           typename IntegralType,
           std::enable_if_t<(std::is_integral<IntegralType>::value)> const* = nullptr>
  WIDE_INTEGER_CONSTEXPR auto eval_right_shift(uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>& result, const IntegralType& n) -> void
  {
    result.representation() >>= n;
  }

  template<
  #if defined(WIDE_INTEGER_NAMESPACE)
           const WIDE_INTEGER_NAMESPACE::math::wide_integer::size_t MyWidth2,
  #else
           const ::math::wide_integer::size_t MyWidth2,
  #endif
           typename MyLimbType,
           typename MyAllocatorType>
  constexpr auto eval_lsb(const uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>& a) -> unsigned
  {
    return static_cast<unsigned>(lsb(a.crepresentation()));
  }

  template<
  #if defined(WIDE_INTEGER_NAMESPACE)
           const WIDE_INTEGER_NAMESPACE::math::wide_integer::size_t MyWidth2,
  #else
           const ::math::wide_integer::size_t MyWidth2,
  #endif
           typename MyLimbType,
           typename MyAllocatorType>
  constexpr auto eval_msb(const uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>& a) -> unsigned
  {
    return static_cast<unsigned>(msb(a.crepresentation()));
  }

  template<
  #if defined(WIDE_INTEGER_NAMESPACE)
           const WIDE_INTEGER_NAMESPACE::math::wide_integer::size_t MyWidth2,
  #else
           const ::math::wide_integer::size_t MyWidth2,
  #endif
           typename MyLimbType,
           typename MyAllocatorType>
  constexpr auto eval_eq(const uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>& a,
                         const uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>& b) -> bool
  {
    return (a.compare(b) == 0);
  }

  template<
  #if defined(WIDE_INTEGER_NAMESPACE)
           const WIDE_INTEGER_NAMESPACE::math::wide_integer::size_t MyWidth2,
  #else
           const ::math::wide_integer::size_t MyWidth2,
  #endif
           typename MyLimbType,
           typename MyAllocatorType,
           typename ArithmeticType,
           std::enable_if_t<(std::is_arithmetic <ArithmeticType>::value)> const* = nullptr>
  constexpr auto eval_eq(const uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>& a,
                               ArithmeticType                                             b) -> bool
  {
    return (a.compare(b) == 0);
  }

  template<
  #if defined(WIDE_INTEGER_NAMESPACE)
           const WIDE_INTEGER_NAMESPACE::math::wide_integer::size_t MyWidth2,
  #else
           const ::math::wide_integer::size_t MyWidth2,
  #endif
           typename MyLimbType,
           typename MyAllocatorType,
           typename ArithmeticType,
           std::enable_if_t<(std::is_arithmetic <ArithmeticType>::value)> const* = nullptr>
  constexpr auto eval_eq(      ArithmeticType                                             a,
                         const uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>& b) -> bool
  {
    return (uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>(a).compare(b) == 0);
  }

  template<
  #if defined(WIDE_INTEGER_NAMESPACE)
           const WIDE_INTEGER_NAMESPACE::math::wide_integer::size_t MyWidth2,
  #else
           const ::math::wide_integer::size_t MyWidth2,
  #endif
           typename MyLimbType,
           typename MyAllocatorType>
  constexpr auto eval_gt(const uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>& a,
                         const uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>& b) -> bool
  {
    return (a.compare(b) == 1);
  }

  template<
  #if defined(WIDE_INTEGER_NAMESPACE)
           const WIDE_INTEGER_NAMESPACE::math::wide_integer::size_t MyWidth2,
  #else
           const ::math::wide_integer::size_t MyWidth2,
  #endif
           typename MyLimbType,
           typename MyAllocatorType,
           typename ArithmeticType,
           std::enable_if_t<(std::is_arithmetic <ArithmeticType>::value)> const* = nullptr>
  constexpr auto eval_gt(const uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>& a,
                               ArithmeticType                                             b) -> bool
  {
    return (a.compare(b) == 1);
  }

  template<
  #if defined(WIDE_INTEGER_NAMESPACE)
           const WIDE_INTEGER_NAMESPACE::math::wide_integer::size_t MyWidth2,
  #else
           const ::math::wide_integer::size_t MyWidth2,
  #endif
           typename MyLimbType,
           typename MyAllocatorType,
           typename ArithmeticType,
           std::enable_if_t<(std::is_arithmetic <ArithmeticType>::value)> const* = nullptr>
  constexpr auto eval_gt(      ArithmeticType                                             a,
                         const uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>& b) -> bool
  {
    return (uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>(a).compare(b) == 1);
  }

  template<
  #if defined(WIDE_INTEGER_NAMESPACE)
           const WIDE_INTEGER_NAMESPACE::math::wide_integer::size_t MyWidth2,
  #else
           const ::math::wide_integer::size_t MyWidth2,
  #endif
           typename MyLimbType,
           typename MyAllocatorType>
  constexpr auto eval_lt(const uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>& a,
                         const uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>& b) -> bool
  {
    return (a.compare(b) == -1);
  }

  template<
  #if defined(WIDE_INTEGER_NAMESPACE)
           const WIDE_INTEGER_NAMESPACE::math::wide_integer::size_t MyWidth2,
  #else
           const ::math::wide_integer::size_t MyWidth2,
  #endif
           typename MyLimbType,
           typename MyAllocatorType,
           typename ArithmeticType,
           std::enable_if_t<(std::is_arithmetic <ArithmeticType>::value)> const* = nullptr>
  constexpr auto eval_lt(const uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>& a,
                               ArithmeticType                                             b) -> bool
  {
    return (a.compare(b) == -1);
  }

  template<
  #if defined(WIDE_INTEGER_NAMESPACE)
           const WIDE_INTEGER_NAMESPACE::math::wide_integer::size_t MyWidth2,
  #else
           const ::math::wide_integer::size_t MyWidth2,
  #endif
           typename MyLimbType,
           typename MyAllocatorType,
           typename ArithmeticType,
           std::enable_if_t<(std::is_arithmetic <ArithmeticType>::value)> const* = nullptr>
  constexpr auto eval_lt(      ArithmeticType                                             a,
                         const uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>& b) -> bool
  {
    return (uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>(a).compare(b) == -1);
  }

  template<
  #if defined(WIDE_INTEGER_NAMESPACE)
           const WIDE_INTEGER_NAMESPACE::math::wide_integer::size_t MyWidth2,
  #else
           const ::math::wide_integer::size_t MyWidth2,
  #endif
           typename MyLimbType,
           typename MyAllocatorType>
  constexpr auto eval_is_zero(const uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>& x) -> bool
  {
    return (x.crepresentation().is_zero());
  }

  template<
  #if defined(WIDE_INTEGER_NAMESPACE)
           const WIDE_INTEGER_NAMESPACE::math::wide_integer::size_t MyWidth2,
  #else
           const ::math::wide_integer::size_t MyWidth2,
  #endif
           typename MyLimbType,
           typename MyAllocatorType>
  constexpr auto eval_get_sign(const uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>& x) -> int
  {
    return (eval_is_zero(x) ? 0 : 1);
  }

  template<typename UnsignedIntegralType,
  #if defined(WIDE_INTEGER_NAMESPACE)
           const WIDE_INTEGER_NAMESPACE::math::wide_integer::size_t MyWidth2,
  #else
           const ::math::wide_integer::size_t MyWidth2,
  #endif
           typename MyLimbType,
           typename MyAllocatorType>
  WIDE_INTEGER_CONSTEXPR auto eval_convert_to
  (
          UnsignedIntegralType*                                                                 result,
    const uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>&                            val,
          std::enable_if_t<(    (std::is_integral<UnsignedIntegralType>::value)
                            && (!std::is_signed  <UnsignedIntegralType>::value))>* p_nullparam = nullptr
  ) -> void
  {
    static_cast<void>(p_nullparam);

    using local_unsigned_integral_type = UnsignedIntegralType;

    static_assert((!std::is_signed<local_unsigned_integral_type>::value),
                  "Error: Wrong signed instantiation (destination type should be unsigned).");

    *result = static_cast<local_unsigned_integral_type>(val.crepresentation());
  }

  template<typename SignedIntegralType,
  #if defined(WIDE_INTEGER_NAMESPACE)
           const WIDE_INTEGER_NAMESPACE::math::wide_integer::size_t MyWidth2,
  #else
           const ::math::wide_integer::size_t MyWidth2,
  #endif
           typename MyLimbType,
           typename MyAllocatorType>
  WIDE_INTEGER_CONSTEXPR auto eval_convert_to
  (
          SignedIntegralType*                                                                result,
    const uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>&                         val,
          std::enable_if_t<(   (std::is_integral<SignedIntegralType>::value)
                            && (std::is_signed  <SignedIntegralType>::value))>* p_nullparam = nullptr
  ) -> void
  {
    static_cast<void>(p_nullparam);

    using local_signed_integral_type = SignedIntegralType;

    static_assert(std::is_signed<local_signed_integral_type>::value,
                  "Error: Wrong unsigned instantiation (destination type should be signed).");

    *result = static_cast<local_signed_integral_type>(val.crepresentation());
  }

  template<
  #if defined(WIDE_INTEGER_NAMESPACE)
           const WIDE_INTEGER_NAMESPACE::math::wide_integer::size_t MyWidth2,
  #else
           const ::math::wide_integer::size_t MyWidth2,
  #endif
           typename MyLimbType,
           typename MyAllocatorType>
  WIDE_INTEGER_CONSTEXPR auto eval_convert_to(long double* result,
                                              const uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>& val) -> void
  {
    *result = static_cast<long double>(val.crepresentation());
  }

  template<
  #if defined(WIDE_INTEGER_NAMESPACE)
           const WIDE_INTEGER_NAMESPACE::math::wide_integer::size_t MyWidth2,
  #else
           const ::math::wide_integer::size_t MyWidth2,
  #endif
           typename MyLimbType,
           typename MyAllocatorType>
  constexpr auto hash_value(const uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>& val) -> std::size_t
  {
    return val.hash();
  }

  #if(__cplusplus >= 201703L)
  } // namespace boost::multiprecision
  #else
  } // namespace multiprecision
  } // namespace boost
  #endif

  #if (BOOST_VERSION < 107900)

  #if(__cplusplus >= 201703L)
  namespace boost::math::policies {
  #else
  namespace boost { namespace math { namespace policies { // NOLINT(modernize-concat-nested-namespaces)
  #endif

  // Specialization of the precision structure.
  template<
  #if defined(WIDE_INTEGER_NAMESPACE)
           const WIDE_INTEGER_NAMESPACE::math::wide_integer::size_t MyWidth2,
  #else
           const ::math::wide_integer::size_t MyWidth2,
  #endif
           typename MyLimbType,
           typename MyAllocatorType,
           typename ThisPolicy,
           const boost::multiprecision::expression_template_option ExpressionTemplatesOptions>
  struct precision<boost::multiprecision::number<boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>,
                                                 ExpressionTemplatesOptions>,
                   ThisPolicy>
  {
    using precision_type = typename ThisPolicy::precision_type;

    using local_digits_2 = digits2<MyWidth2>;

    #if (BOOST_VERSION <= 107500)
    using type = typename mpl::if_c       <((local_digits_2::value <= precision_type::value) || (precision_type::value <= 0)),
                                             local_digits_2,
                                             precision_type>::type;
    #else
    using type = typename std::conditional<((local_digits_2::value <= precision_type::value) || (precision_type::value <= 0)),
                                             local_digits_2,
                                             precision_type>::type;
    #endif
  };

  #if(__cplusplus >= 201703L)
  } // namespace boost::math::policies
  #else
  } // namespace policies
  } // namespace math
  } // namespace boost
  #endif

  #endif

  namespace std // NOLINT(cert-dcl58-cpp)
  {
    template<
    #if defined(WIDE_INTEGER_NAMESPACE)
             const WIDE_INTEGER_NAMESPACE::math::wide_integer::size_t MyWidth2,
    #else
             const ::math::wide_integer::size_t MyWidth2,
    #endif
             typename MyLimbType,
             typename MyAllocatorType,
             const boost::multiprecision::expression_template_option ExpressionTemplatesOptions>
    class numeric_limits<boost::multiprecision::number<boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>,
                                                       ExpressionTemplatesOptions>>
    {
    public:
      static constexpr bool is_specialized = true;
      static constexpr bool is_signed      = false;
      static constexpr bool is_integer     = true;
      static constexpr bool is_exact       = true;
      static constexpr bool is_bounded     = true;
      static constexpr bool is_modulo      = false;
      static constexpr bool is_iec559      = false;
      static constexpr int  digits         = MyWidth2;
      static constexpr int  digits10       = static_cast<int>((MyWidth2 * 301LL) / 1000LL);
      static constexpr int  max_digits10   = static_cast<int>((MyWidth2 * 301LL) / 1000LL);

      #if defined(WIDE_INTEGER_NAMESPACE)
      static constexpr int max_exponent    = std::numeric_limits<WIDE_INTEGER_NAMESPACE::math::wide_integer::uintwide_t<MyWidth2, MyLimbType, MyAllocatorType>>::max_exponent;
      static constexpr int max_exponent10  = std::numeric_limits<WIDE_INTEGER_NAMESPACE::math::wide_integer::uintwide_t<MyWidth2, MyLimbType, MyAllocatorType>>::max_exponent10;
      static constexpr int min_exponent    = std::numeric_limits<WIDE_INTEGER_NAMESPACE::math::wide_integer::uintwide_t<MyWidth2, MyLimbType, MyAllocatorType>>::min_exponent;
      static constexpr int min_exponent10  = std::numeric_limits<WIDE_INTEGER_NAMESPACE::math::wide_integer::uintwide_t<MyWidth2, MyLimbType, MyAllocatorType>>::min_exponent10;
      #else
      static constexpr int max_exponent    = std::numeric_limits<::math::wide_integer::uintwide_t<MyWidth2, MyLimbType, MyAllocatorType>>::max_exponent;
      static constexpr int max_exponent10  = std::numeric_limits<::math::wide_integer::uintwide_t<MyWidth2, MyLimbType, MyAllocatorType>>::max_exponent10;
      static constexpr int min_exponent    = std::numeric_limits<::math::wide_integer::uintwide_t<MyWidth2, MyLimbType, MyAllocatorType>>::min_exponent;
      static constexpr int min_exponent10  = std::numeric_limits<::math::wide_integer::uintwide_t<MyWidth2, MyLimbType, MyAllocatorType>>::min_exponent10;
      #endif

      static constexpr int                     radix             = 2;
      static constexpr std::float_round_style  round_style       = std::round_to_nearest;
      static constexpr bool                    has_infinity      = false;
      static constexpr bool                    has_quiet_NaN     = false;
      static constexpr bool                    has_signaling_NaN = false;
      static constexpr std::float_denorm_style has_denorm        = std::denorm_absent;
      static constexpr bool                    has_denorm_loss   = false;
      static constexpr bool                    traps             = false;
      static constexpr bool                    tinyness_before   = false;

      #if defined(WIDE_INTEGER_NAMESPACE)
      static WIDE_INTEGER_CONSTEXPR auto (min)        () -> boost::multiprecision::number<boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>, ExpressionTemplatesOptions> { return boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>((std::numeric_limits<WIDE_INTEGER_NAMESPACE::math::wide_integer::uintwide_t<MyWidth2, MyLimbType, MyAllocatorType>>::min)()       ); }
      static WIDE_INTEGER_CONSTEXPR auto (max)        () -> boost::multiprecision::number<boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>, ExpressionTemplatesOptions> { return boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>((std::numeric_limits<WIDE_INTEGER_NAMESPACE::math::wide_integer::uintwide_t<MyWidth2, MyLimbType, MyAllocatorType>>::max)()       ); }
      static WIDE_INTEGER_CONSTEXPR auto lowest       () -> boost::multiprecision::number<boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>, ExpressionTemplatesOptions> { return boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType> (std::numeric_limits<WIDE_INTEGER_NAMESPACE::math::wide_integer::uintwide_t<MyWidth2, MyLimbType, MyAllocatorType>>::lowest       ); }
      static WIDE_INTEGER_CONSTEXPR auto epsilon      () -> boost::multiprecision::number<boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>, ExpressionTemplatesOptions> { return boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType> (std::numeric_limits<WIDE_INTEGER_NAMESPACE::math::wide_integer::uintwide_t<MyWidth2, MyLimbType, MyAllocatorType>>::epsilon      ); }
      static WIDE_INTEGER_CONSTEXPR auto round_error  () -> boost::multiprecision::number<boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>, ExpressionTemplatesOptions> { return boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType> (std::numeric_limits<WIDE_INTEGER_NAMESPACE::math::wide_integer::uintwide_t<MyWidth2, MyLimbType, MyAllocatorType>>::round_error  ); }
      static WIDE_INTEGER_CONSTEXPR auto infinity     () -> boost::multiprecision::number<boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>, ExpressionTemplatesOptions> { return boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType> (std::numeric_limits<WIDE_INTEGER_NAMESPACE::math::wide_integer::uintwide_t<MyWidth2, MyLimbType, MyAllocatorType>>::infinity     ); }
      static WIDE_INTEGER_CONSTEXPR auto quiet_NaN    () -> boost::multiprecision::number<boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>, ExpressionTemplatesOptions> { return boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType> (std::numeric_limits<WIDE_INTEGER_NAMESPACE::math::wide_integer::uintwide_t<MyWidth2, MyLimbType, MyAllocatorType>>::quiet_NaN    ); } // NOLINT(readability-identifier-naming)
      static WIDE_INTEGER_CONSTEXPR auto signaling_NaN() -> boost::multiprecision::number<boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>, ExpressionTemplatesOptions> { return boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType> (std::numeric_limits<WIDE_INTEGER_NAMESPACE::math::wide_integer::uintwide_t<MyWidth2, MyLimbType, MyAllocatorType>>::signaling_NaN); } // NOLINT(readability-identifier-naming)
      static WIDE_INTEGER_CONSTEXPR auto denorm_min   () -> boost::multiprecision::number<boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>, ExpressionTemplatesOptions> { return boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType> (std::numeric_limits<WIDE_INTEGER_NAMESPACE::math::wide_integer::uintwide_t<MyWidth2, MyLimbType, MyAllocatorType>>::denorm_min   ); }
      #else
      static WIDE_INTEGER_CONSTEXPR auto (min)        () -> boost::multiprecision::number<boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>, ExpressionTemplatesOptions> { return boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>((std::numeric_limits<::math::wide_integer::uintwide_t<MyWidth2, MyLimbType, MyAllocatorType>>::min)()       ); }
      static WIDE_INTEGER_CONSTEXPR auto (max)        () -> boost::multiprecision::number<boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>, ExpressionTemplatesOptions> { return boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>((std::numeric_limits<::math::wide_integer::uintwide_t<MyWidth2, MyLimbType, MyAllocatorType>>::max)()       ); }
      static WIDE_INTEGER_CONSTEXPR auto lowest       () -> boost::multiprecision::number<boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>, ExpressionTemplatesOptions> { return boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType> (std::numeric_limits<::math::wide_integer::uintwide_t<MyWidth2, MyLimbType, MyAllocatorType>>::lowest       ); }
      static WIDE_INTEGER_CONSTEXPR auto epsilon      () -> boost::multiprecision::number<boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>, ExpressionTemplatesOptions> { return boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType> (std::numeric_limits<::math::wide_integer::uintwide_t<MyWidth2, MyLimbType, MyAllocatorType>>::epsilon      ); }
      static WIDE_INTEGER_CONSTEXPR auto round_error  () -> boost::multiprecision::number<boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>, ExpressionTemplatesOptions> { return boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType> (std::numeric_limits<::math::wide_integer::uintwide_t<MyWidth2, MyLimbType, MyAllocatorType>>::round_error  ); }
      static WIDE_INTEGER_CONSTEXPR auto infinity     () -> boost::multiprecision::number<boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>, ExpressionTemplatesOptions> { return boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType> (std::numeric_limits<::math::wide_integer::uintwide_t<MyWidth2, MyLimbType, MyAllocatorType>>::infinity     ); }
      static WIDE_INTEGER_CONSTEXPR auto quiet_NaN    () -> boost::multiprecision::number<boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>, ExpressionTemplatesOptions> { return boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType> (std::numeric_limits<::math::wide_integer::uintwide_t<MyWidth2, MyLimbType, MyAllocatorType>>::quiet_NaN    ); } // NOLINT(readability-identifier-naming)
      static WIDE_INTEGER_CONSTEXPR auto signaling_NaN() -> boost::multiprecision::number<boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>, ExpressionTemplatesOptions> { return boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType> (std::numeric_limits<::math::wide_integer::uintwide_t<MyWidth2, MyLimbType, MyAllocatorType>>::signaling_NaN); } // NOLINT(readability-identifier-naming)
      static WIDE_INTEGER_CONSTEXPR auto denorm_min   () -> boost::multiprecision::number<boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>, ExpressionTemplatesOptions> { return boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType> (std::numeric_limits<::math::wide_integer::uintwide_t<MyWidth2, MyLimbType, MyAllocatorType>>::denorm_min   ); }
      #endif
    };

    #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION

    #if defined(WIDE_INTEGER_NAMESPACE)
    template<const WIDE_INTEGER_NAMESPACE::math::wide_integer::size_t MyWidth2, typename MyLimbType, typename MyAllocatorType, const boost::multiprecision::expression_template_option ExpressionTemplatesOptions> constexpr bool std::numeric_limits<boost::multiprecision::number<boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>, ExpressionTemplatesOptions>>::is_specialized; // NOLINT(readability-redundant-declaration)
    template<const WIDE_INTEGER_NAMESPACE::math::wide_integer::size_t MyWidth2, typename MyLimbType, typename MyAllocatorType, const boost::multiprecision::expression_template_option ExpressionTemplatesOptions> constexpr bool std::numeric_limits<boost::multiprecision::number<boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>, ExpressionTemplatesOptions>>::is_signed;      // NOLINT(readability-redundant-declaration)
    template<const WIDE_INTEGER_NAMESPACE::math::wide_integer::size_t MyWidth2, typename MyLimbType, typename MyAllocatorType, const boost::multiprecision::expression_template_option ExpressionTemplatesOptions> constexpr bool std::numeric_limits<boost::multiprecision::number<boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>, ExpressionTemplatesOptions>>::is_integer;     // NOLINT(readability-redundant-declaration)
    template<const WIDE_INTEGER_NAMESPACE::math::wide_integer::size_t MyWidth2, typename MyLimbType, typename MyAllocatorType, const boost::multiprecision::expression_template_option ExpressionTemplatesOptions> constexpr bool std::numeric_limits<boost::multiprecision::number<boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>, ExpressionTemplatesOptions>>::is_exact;       // NOLINT(readability-redundant-declaration)
    template<const WIDE_INTEGER_NAMESPACE::math::wide_integer::size_t MyWidth2, typename MyLimbType, typename MyAllocatorType, const boost::multiprecision::expression_template_option ExpressionTemplatesOptions> constexpr bool std::numeric_limits<boost::multiprecision::number<boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>, ExpressionTemplatesOptions>>::is_bounded;     // NOLINT(readability-redundant-declaration)
    template<const WIDE_INTEGER_NAMESPACE::math::wide_integer::size_t MyWidth2, typename MyLimbType, typename MyAllocatorType, const boost::multiprecision::expression_template_option ExpressionTemplatesOptions> constexpr bool std::numeric_limits<boost::multiprecision::number<boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>, ExpressionTemplatesOptions>>::is_modulo;      // NOLINT(readability-redundant-declaration)
    template<const WIDE_INTEGER_NAMESPACE::math::wide_integer::size_t MyWidth2, typename MyLimbType, typename MyAllocatorType, const boost::multiprecision::expression_template_option ExpressionTemplatesOptions> constexpr bool std::numeric_limits<boost::multiprecision::number<boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>, ExpressionTemplatesOptions>>::is_iec559;      // NOLINT(readability-redundant-declaration)
    template<const WIDE_INTEGER_NAMESPACE::math::wide_integer::size_t MyWidth2, typename MyLimbType, typename MyAllocatorType, const boost::multiprecision::expression_template_option ExpressionTemplatesOptions> constexpr int  std::numeric_limits<boost::multiprecision::number<boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>, ExpressionTemplatesOptions>>::digits;         // NOLINT(readability-redundant-declaration)
    template<const WIDE_INTEGER_NAMESPACE::math::wide_integer::size_t MyWidth2, typename MyLimbType, typename MyAllocatorType, const boost::multiprecision::expression_template_option ExpressionTemplatesOptions> constexpr int  std::numeric_limits<boost::multiprecision::number<boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>, ExpressionTemplatesOptions>>::digits10;       // NOLINT(readability-redundant-declaration)
    template<const WIDE_INTEGER_NAMESPACE::math::wide_integer::size_t MyWidth2, typename MyLimbType, typename MyAllocatorType, const boost::multiprecision::expression_template_option ExpressionTemplatesOptions> constexpr int  std::numeric_limits<boost::multiprecision::number<boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>, ExpressionTemplatesOptions>>::max_digits10;   // NOLINT(readability-redundant-declaration)

    template<const WIDE_INTEGER_NAMESPACE::math::wide_integer::size_t MyWidth2, typename MyLimbType, typename MyAllocatorType, const boost::multiprecision::expression_template_option ExpressionTemplatesOptions> constexpr int std::numeric_limits<boost::multiprecision::number<boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>, ExpressionTemplatesOptions>>::max_exponent;   // NOLINT(readability-redundant-declaration)
    template<const WIDE_INTEGER_NAMESPACE::math::wide_integer::size_t MyWidth2, typename MyLimbType, typename MyAllocatorType, const boost::multiprecision::expression_template_option ExpressionTemplatesOptions> constexpr int std::numeric_limits<boost::multiprecision::number<boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>, ExpressionTemplatesOptions>>::max_exponent10; // NOLINT(readability-redundant-declaration)
    template<const WIDE_INTEGER_NAMESPACE::math::wide_integer::size_t MyWidth2, typename MyLimbType, typename MyAllocatorType, const boost::multiprecision::expression_template_option ExpressionTemplatesOptions> constexpr int std::numeric_limits<boost::multiprecision::number<boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>, ExpressionTemplatesOptions>>::min_exponent;   // NOLINT(readability-redundant-declaration)
    template<const WIDE_INTEGER_NAMESPACE::math::wide_integer::size_t MyWidth2, typename MyLimbType, typename MyAllocatorType, const boost::multiprecision::expression_template_option ExpressionTemplatesOptions> constexpr int std::numeric_limits<boost::multiprecision::number<boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>, ExpressionTemplatesOptions>>::min_exponent10; // NOLINT(readability-redundant-declaration)

    template<const WIDE_INTEGER_NAMESPACE::math::wide_integer::size_t MyWidth2, typename MyLimbType, typename MyAllocatorType, const boost::multiprecision::expression_template_option ExpressionTemplatesOptions> constexpr int                     std::numeric_limits<boost::multiprecision::number<boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>, ExpressionTemplatesOptions>>::radix;             // NOLINT(readability-redundant-declaration)
    template<const WIDE_INTEGER_NAMESPACE::math::wide_integer::size_t MyWidth2, typename MyLimbType, typename MyAllocatorType, const boost::multiprecision::expression_template_option ExpressionTemplatesOptions> constexpr std::float_round_style  std::numeric_limits<boost::multiprecision::number<boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>, ExpressionTemplatesOptions>>::round_style;       // NOLINT(readability-redundant-declaration)
    template<const WIDE_INTEGER_NAMESPACE::math::wide_integer::size_t MyWidth2, typename MyLimbType, typename MyAllocatorType, const boost::multiprecision::expression_template_option ExpressionTemplatesOptions> constexpr bool                    std::numeric_limits<boost::multiprecision::number<boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>, ExpressionTemplatesOptions>>::has_infinity;      // NOLINT(readability-redundant-declaration)
    template<const WIDE_INTEGER_NAMESPACE::math::wide_integer::size_t MyWidth2, typename MyLimbType, typename MyAllocatorType, const boost::multiprecision::expression_template_option ExpressionTemplatesOptions> constexpr bool                    std::numeric_limits<boost::multiprecision::number<boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>, ExpressionTemplatesOptions>>::has_quiet_NaN;     // NOLINT(readability-redundant-declaration)
    template<const WIDE_INTEGER_NAMESPACE::math::wide_integer::size_t MyWidth2, typename MyLimbType, typename MyAllocatorType, const boost::multiprecision::expression_template_option ExpressionTemplatesOptions> constexpr bool                    std::numeric_limits<boost::multiprecision::number<boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>, ExpressionTemplatesOptions>>::has_signaling_NaN; // NOLINT(readability-redundant-declaration)
    template<const WIDE_INTEGER_NAMESPACE::math::wide_integer::size_t MyWidth2, typename MyLimbType, typename MyAllocatorType, const boost::multiprecision::expression_template_option ExpressionTemplatesOptions> constexpr std::float_denorm_style std::numeric_limits<boost::multiprecision::number<boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>, ExpressionTemplatesOptions>>::has_denorm;        // NOLINT(readability-redundant-declaration)
    template<const WIDE_INTEGER_NAMESPACE::math::wide_integer::size_t MyWidth2, typename MyLimbType, typename MyAllocatorType, const boost::multiprecision::expression_template_option ExpressionTemplatesOptions> constexpr bool                    std::numeric_limits<boost::multiprecision::number<boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>, ExpressionTemplatesOptions>>::has_denorm_loss;   // NOLINT(readability-redundant-declaration)
    template<const WIDE_INTEGER_NAMESPACE::math::wide_integer::size_t MyWidth2, typename MyLimbType, typename MyAllocatorType, const boost::multiprecision::expression_template_option ExpressionTemplatesOptions> constexpr bool                    std::numeric_limits<boost::multiprecision::number<boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>, ExpressionTemplatesOptions>>::traps;             // NOLINT(readability-redundant-declaration)
    template<const WIDE_INTEGER_NAMESPACE::math::wide_integer::size_t MyWidth2, typename MyLimbType, typename MyAllocatorType, const boost::multiprecision::expression_template_option ExpressionTemplatesOptions> constexpr bool                    std::numeric_limits<boost::multiprecision::number<boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>, ExpressionTemplatesOptions>>::tinyness_before;   // NOLINT(readability-redundant-declaration)
    #else
    template<const ::math::wide_integer::size_t MyWidth2, typename MyLimbType, typename MyAllocatorType, const boost::multiprecision::expression_template_option ExpressionTemplatesOptions> constexpr bool std::numeric_limits<boost::multiprecision::number<boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>, ExpressionTemplatesOptions>>::is_specialized; // NOLINT(readability-redundant-declaration)
    template<const ::math::wide_integer::size_t MyWidth2, typename MyLimbType, typename MyAllocatorType, const boost::multiprecision::expression_template_option ExpressionTemplatesOptions> constexpr bool std::numeric_limits<boost::multiprecision::number<boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>, ExpressionTemplatesOptions>>::is_signed;      // NOLINT(readability-redundant-declaration)
    template<const ::math::wide_integer::size_t MyWidth2, typename MyLimbType, typename MyAllocatorType, const boost::multiprecision::expression_template_option ExpressionTemplatesOptions> constexpr bool std::numeric_limits<boost::multiprecision::number<boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>, ExpressionTemplatesOptions>>::is_integer;     // NOLINT(readability-redundant-declaration)
    template<const ::math::wide_integer::size_t MyWidth2, typename MyLimbType, typename MyAllocatorType, const boost::multiprecision::expression_template_option ExpressionTemplatesOptions> constexpr bool std::numeric_limits<boost::multiprecision::number<boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>, ExpressionTemplatesOptions>>::is_exact;       // NOLINT(readability-redundant-declaration)
    template<const ::math::wide_integer::size_t MyWidth2, typename MyLimbType, typename MyAllocatorType, const boost::multiprecision::expression_template_option ExpressionTemplatesOptions> constexpr bool std::numeric_limits<boost::multiprecision::number<boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>, ExpressionTemplatesOptions>>::is_bounded;     // NOLINT(readability-redundant-declaration)
    template<const ::math::wide_integer::size_t MyWidth2, typename MyLimbType, typename MyAllocatorType, const boost::multiprecision::expression_template_option ExpressionTemplatesOptions> constexpr bool std::numeric_limits<boost::multiprecision::number<boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>, ExpressionTemplatesOptions>>::is_modulo;      // NOLINT(readability-redundant-declaration)
    template<const ::math::wide_integer::size_t MyWidth2, typename MyLimbType, typename MyAllocatorType, const boost::multiprecision::expression_template_option ExpressionTemplatesOptions> constexpr bool std::numeric_limits<boost::multiprecision::number<boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>, ExpressionTemplatesOptions>>::is_iec559;      // NOLINT(readability-redundant-declaration)
    template<const ::math::wide_integer::size_t MyWidth2, typename MyLimbType, typename MyAllocatorType, const boost::multiprecision::expression_template_option ExpressionTemplatesOptions> constexpr int  std::numeric_limits<boost::multiprecision::number<boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>, ExpressionTemplatesOptions>>::digits;         // NOLINT(readability-redundant-declaration)
    template<const ::math::wide_integer::size_t MyWidth2, typename MyLimbType, typename MyAllocatorType, const boost::multiprecision::expression_template_option ExpressionTemplatesOptions> constexpr int  std::numeric_limits<boost::multiprecision::number<boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>, ExpressionTemplatesOptions>>::digits10;       // NOLINT(readability-redundant-declaration)
    template<const ::math::wide_integer::size_t MyWidth2, typename MyLimbType, typename MyAllocatorType, const boost::multiprecision::expression_template_option ExpressionTemplatesOptions> constexpr int  std::numeric_limits<boost::multiprecision::number<boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>, ExpressionTemplatesOptions>>::max_digits10;   // NOLINT(readability-redundant-declaration)

    template<const ::math::wide_integer::size_t MyWidth2, typename MyLimbType, typename MyAllocatorType, const boost::multiprecision::expression_template_option ExpressionTemplatesOptions> constexpr int std::numeric_limits<boost::multiprecision::number<boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>, ExpressionTemplatesOptions>>::max_exponent;    // NOLINT(readability-redundant-declaration)
    template<const ::math::wide_integer::size_t MyWidth2, typename MyLimbType, typename MyAllocatorType, const boost::multiprecision::expression_template_option ExpressionTemplatesOptions> constexpr int std::numeric_limits<boost::multiprecision::number<boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>, ExpressionTemplatesOptions>>::max_exponent10;  // NOLINT(readability-redundant-declaration)
    template<const ::math::wide_integer::size_t MyWidth2, typename MyLimbType, typename MyAllocatorType, const boost::multiprecision::expression_template_option ExpressionTemplatesOptions> constexpr int std::numeric_limits<boost::multiprecision::number<boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>, ExpressionTemplatesOptions>>::min_exponent;    // NOLINT(readability-redundant-declaration)
    template<const ::math::wide_integer::size_t MyWidth2, typename MyLimbType, typename MyAllocatorType, const boost::multiprecision::expression_template_option ExpressionTemplatesOptions> constexpr int std::numeric_limits<boost::multiprecision::number<boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>, ExpressionTemplatesOptions>>::min_exponent10;  // NOLINT(readability-redundant-declaration)

    template<const ::math::wide_integer::size_t MyWidth2, typename MyLimbType, typename MyAllocatorType, const boost::multiprecision::expression_template_option ExpressionTemplatesOptions> constexpr int                     std::numeric_limits<boost::multiprecision::number<boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>, ExpressionTemplatesOptions>>::radix;             // NOLINT(readability-redundant-declaration)
    template<const ::math::wide_integer::size_t MyWidth2, typename MyLimbType, typename MyAllocatorType, const boost::multiprecision::expression_template_option ExpressionTemplatesOptions> constexpr std::float_round_style  std::numeric_limits<boost::multiprecision::number<boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>, ExpressionTemplatesOptions>>::round_style;       // NOLINT(readability-redundant-declaration)
    template<const ::math::wide_integer::size_t MyWidth2, typename MyLimbType, typename MyAllocatorType, const boost::multiprecision::expression_template_option ExpressionTemplatesOptions> constexpr bool                    std::numeric_limits<boost::multiprecision::number<boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>, ExpressionTemplatesOptions>>::has_infinity;      // NOLINT(readability-redundant-declaration)
    template<const ::math::wide_integer::size_t MyWidth2, typename MyLimbType, typename MyAllocatorType, const boost::multiprecision::expression_template_option ExpressionTemplatesOptions> constexpr bool                    std::numeric_limits<boost::multiprecision::number<boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>, ExpressionTemplatesOptions>>::has_quiet_NaN;     // NOLINT(readability-redundant-declaration)
    template<const ::math::wide_integer::size_t MyWidth2, typename MyLimbType, typename MyAllocatorType, const boost::multiprecision::expression_template_option ExpressionTemplatesOptions> constexpr bool                    std::numeric_limits<boost::multiprecision::number<boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>, ExpressionTemplatesOptions>>::has_signaling_NaN; // NOLINT(readability-redundant-declaration)
    template<const ::math::wide_integer::size_t MyWidth2, typename MyLimbType, typename MyAllocatorType, const boost::multiprecision::expression_template_option ExpressionTemplatesOptions> constexpr std::float_denorm_style std::numeric_limits<boost::multiprecision::number<boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>, ExpressionTemplatesOptions>>::has_denorm;        // NOLINT(readability-redundant-declaration)
    template<const ::math::wide_integer::size_t MyWidth2, typename MyLimbType, typename MyAllocatorType, const boost::multiprecision::expression_template_option ExpressionTemplatesOptions> constexpr bool                    std::numeric_limits<boost::multiprecision::number<boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>, ExpressionTemplatesOptions>>::has_denorm_loss;   // NOLINT(readability-redundant-declaration)
    template<const ::math::wide_integer::size_t MyWidth2, typename MyLimbType, typename MyAllocatorType, const boost::multiprecision::expression_template_option ExpressionTemplatesOptions> constexpr bool                    std::numeric_limits<boost::multiprecision::number<boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>, ExpressionTemplatesOptions>>::traps;             // NOLINT(readability-redundant-declaration)
    template<const ::math::wide_integer::size_t MyWidth2, typename MyLimbType, typename MyAllocatorType, const boost::multiprecision::expression_template_option ExpressionTemplatesOptions> constexpr bool                    std::numeric_limits<boost::multiprecision::number<boost::multiprecision::uintwide_t_backend<MyWidth2, MyLimbType, MyAllocatorType>, ExpressionTemplatesOptions>>::tinyness_before;   // NOLINT(readability-redundant-declaration)
    #endif

    #endif // !BOOST_NO_INCLASS_MEMBER_INITIALIZATION

  } // namespace std

  #if (BOOST_VERSION < 108000)
  #if (defined(__clang__) && (__clang_major__ > 9)) && !defined(__APPLE__)
  #pragma GCC diagnostic pop
  #endif
  #endif

  #if (defined(__GNUC__) && !defined(__clang__) && (__GNUC__ >= 12))
  #pragma GCC diagnostic pop
  #endif

  #if (BOOST_VERSION < 108000)
  #if defined(__GNUC__)
  #pragma GCC diagnostic pop
  #pragma GCC diagnostic pop
  #pragma GCC diagnostic pop
  #endif
  #endif

#endif // UINTWIDE_T_BACKEND_2019_12_15_HPP


//
// Copyright Fabien Dekeyser, Quoc-Cuong Pham 2008
//
// 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_NUMERIC_BINDINGS_LAPACK_SYGV_HPP
#define BOOST_NUMERIC_BINDINGS_LAPACK_SYGV_HPP

#include <boost/numeric/bindings/lapack/hegv.hpp>

namespace boost { namespace numeric { namespace bindings {
  namespace lapack {

    template <typename A, typename B, typename W, typename Work>
    int sygv (int itype, char jobz, char uplo, A& a, B& b, W& w, Work work = optimal_workspace()) {

#ifndef BOOST_NUMERIC_BINDINGS_NO_STRUCTURE_CHECK
      typedef typename A::value_type                               value_type ;
      typedef typename traits::type_traits< value_type >::real_type real_type ;
      BOOST_STATIC_ASSERT((boost::is_same<value_type, real_type>::value));
#endif

      return hegv (itype, jobz, uplo, a, b, w, work);
    }
  }

}}}

#endif


/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\
|  Phycas: Python software for phylogenetic analysis                          |
|  Copyright (C) 2006 Mark T. Holder, Paul O. Lewis and David L. Swofford     |
|                                                                             |
|  This program is free software; you can redistribute it and/or modify       |
|  it under the terms of the GNU General Public License as published by       |
|  the Free Software Foundation; either version 2 of the License, or          |
|  (at your option) any later version.                                        |
|                                                                             |
|  This program is distributed in the hope that it will be useful,            |
|  but WITHOUT ANY WARRANTY; without even the implied warranty of             |
|  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              |
|  GNU General Public License for more details.                               |
|                                                                             |
|  You should have received a copy of the GNU General Public License along    |
|  with this program; if not, write to the Free Software Foundation, Inc.,    |
|  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.                |
\~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

#if ! defined(HKY_MODEL_HPP)
#define HKY_MODEL_HPP

#include "states_patterns.hpp"
#include "model.hpp"
#include <boost/shared_ptr.hpp>

namespace phycas{

/*----------------------------------------------------------------------------------------------------------------------
|	Specialization of the base class Model that represents the Hasegawa-Kishino-Yano (1985) model.
*/
class HKY: public Model
	{
	public:
                                        HKY();
                                        ~HKY();

		virtual std::string             getModelName() const;
        virtual void                    createParameters(JointPriorManagerShPtr jpm, TreeShPtr t, MCMCUpdaterVect & edgelens, MCMCUpdaterVect & edgelen_hyperparams, MCMCUpdaterVect & parameters, int subset_pos);
		double                          calcUniformizationLambda() const;
        double                          calcLMat(double * * lMat) const;
        double                          calcUMat(double * * uMat) const;
        void                            calcPMat(double * * pMat, double edgeLength) const;

        void                            fixKappa();
		void                            freeKappa();

        double                          getKappa();
		void                            setKappa(double k);

        void                            setKappaPrior(ProbDistShPtr d);
		ProbDistShPtr                   getKappaPrior();

        void                            setKappaFromTRatio(double tratio);
		double                          calcTRatio();

		void                            setStateFreqPrior(MultivarProbDistShPtr d);
		MultivarProbDistShPtr           getStateFreqPrior();

		void                            setStateFreqParamPrior(ProbDistShPtr d);
		ProbDistShPtr                   getStateFreqParamPrior();

		virtual std::string             paramHeader() const;
		virtual std::string             paramReport(unsigned ndecimals, bool include_edgelen_hyperparams) const;

        virtual unsigned                getNumFreeParameters() const;
        virtual void                    appendPWKParamNames(std::vector<std::string> & names, std::string prefix = "") const;
        virtual void                    appendFreeParamNames(std::vector<std::string> & names, std::string prefix = "") const;
        virtual void                    appendParamNames(std::vector<std::string> & names, std::string prefix = "") const;
        virtual void                    appendUntransformedParamValues(std::vector<double> & values) const;
        virtual void                    appendTransformedParamValues(std::vector<double> & values) const;
        virtual bool                    setParamValueFromTransformed(std::string parameter_name, double transformed_value, TreeShPtr tree);
        virtual double                  calcLogDetJacobian() const;

protected:

	ProbDistShPtr				kappa_prior;		/**< The prior distribution governing kappa */
	ProbDistShPtr				freq_param_prior;	/**< The prior distribution governing each frequency parameter (used if frequencies are updated separately by slice sampling) */
	MultivarProbDistShPtr		freq_prior;	        /**< The prior distribution governing the vector of frequencies (used if frequencies are updated jointly by StateFreqMove) */
	bool						kappa_fixed;		/**< If true, the value of kappa will not change during MCMC updates */
	mutable MCMCUpdaterShPtr	kappa_param;		/**< Copy of the kappa parameter (saved so that fixed/free status can be changed) */

	string_vect_t				freq_name;				/**< Holds names of the 4 state frequencies (e.g. freqA, freqC, freqG, freqT) used as headers in the param file */

	// Below here are quantities that directly affect likelihood calculations and which should increment time_stamp when modified
	double						kappa;				/**< The transition/transversion rate ratio */
	};

typedef boost::shared_ptr<HKY> HKYShPtr;

}

#endif


#include <boost/python.hpp>
#include <boost/python/numpy.hpp>

#include <valarray>
#include <cmath>
#include <fstream>
#include <random>
#include <iostream>
#include <chrono>
#include <string>

#include "advect_in_time.h"

namespace p = boost::python;
namespace np = boost::python::numpy;

class Simulation_cpp
{
private:
    std::valarray<double> h;
    std::valarray<double> q;
    std::valarray<int> jet_pos;
    std::valarray<double> jet_power;
    std::valarray<double> jet_power_old;
    std::valarray<double> Noise;

    double L;
    int NUM;
    double dx;
    double dt;
    double delta;
    double noise_mag;
    unsigned int n_step;
    unsigned int n_step2;

    int half_width_jet;
    double t;

    bool flag;
public:
    // Constructor
    Simulation_cpp(np::ndarray new_jet_pos,
                                  double _L,
                                  int _NUM,
                                  double _dx,
                                  double _dt,
                                  double _delta,
                                  double _noise_mag,
                                  unsigned int _n_step,
                                  unsigned int _n_step2,
                                  int _half_width_jet)
    {
        jet_pos = to_valarray_int(new_jet_pos);
        L = _L;
        NUM = _NUM;
        dx = _dx;
        dt = _dt;
        delta = _delta;
        noise_mag = _noise_mag;
        n_step = _n_step;
        n_step2 = _n_step2;
        half_width_jet = _half_width_jet;

        std::valarray<double> Noise1(n_step);
        Noise = Noise1;
        double t = 0.0;
        flag = true;
    }

    // Member functions
    std::valarray<double> to_valarray(np::ndarray array_from_py);
    std::valarray<int> to_valarray_int(np::ndarray array_from_py);
    void set_h(np::ndarray array_from_py);
    void set_q(np::ndarray array_from_py);
    void set_jet_power(np::ndarray array_from_py);

    void next_step();

    np::ndarray to_ndarray(std::valarray<double> & valarray_to_numpy);
    np::ndarray get_h();
    np::ndarray get_q();
    double get_time();
};

// Takes every element of array to given exponent
void Simulation_cpp::next_step()
{
  for (unsigned int i = 0; i < Noise.size(); i++)
  {
    Noise[i] = static_cast <float> (rand())/static_cast <float> (RAND_MAX) * noise_mag;
  }
  ait::advect_in_time(h, q, Noise,
                n_step,
                dx,
                dt,
                delta, t,
                half_width_jet,
                jet_pos,
                jet_power_old,
                jet_power,
                NUM);
}

std::valarray<double> Simulation_cpp::to_valarray(np::ndarray array_from_py)
{
  int len_array_from_py = array_from_py.shape(0);
  std::valarray<double> new_valarray(len_array_from_py);
  for(int i=0; i<len_array_from_py; i++)
  {
    new_valarray[i] = p::extract<double>(array_from_py[i]);
  }
  return new_valarray;
}

std::valarray<int> Simulation_cpp::to_valarray_int(np::ndarray array_from_py)
{
  int len_array_from_py = array_from_py.shape(0);
  std::valarray<int> new_valarray(len_array_from_py);
  for(int i=0; i<len_array_from_py; i++)
  {
    new_valarray[i] = p::extract<int>(array_from_py[i]);
  }
  return new_valarray;
}

void Simulation_cpp::set_h(np::ndarray array_from_py)
{
  h = Simulation_cpp::to_valarray(array_from_py);
}
void Simulation_cpp::set_q(np::ndarray array_from_py)
{
  q = Simulation_cpp::to_valarray(array_from_py);
}
void Simulation_cpp::set_jet_power(np::ndarray array_from_py)
{
  jet_power_old = jet_power;
  jet_power = Simulation_cpp::to_valarray(array_from_py);
  if (flag)
  {
    jet_power_old = Simulation_cpp::to_valarray(array_from_py);
    flag = false;
  }
}

// Takes valarray, returns np::ndarray - it's a deep copy
np::ndarray Simulation_cpp::to_ndarray(std::valarray<double> & valarray_to_numpy)
{
    int array_size = valarray_to_numpy.size();
    p::tuple shape = p::make_tuple(array_size);
    p::tuple stride = p::make_tuple(sizeof(double));
    np::dtype dt = np::dtype::get_builtin<double>();
    np::ndarray ndarray = np::from_data(&valarray_to_numpy[0], dt, shape, stride, p::object());
    return ndarray.copy();
}

// Return array to Python
np::ndarray Simulation_cpp::get_h()
{
  return Simulation_cpp::to_ndarray(h);
}
np::ndarray Simulation_cpp::get_q()
{
  return Simulation_cpp::to_ndarray(q);
}
double Simulation_cpp::get_time()
{
  return t;
}

BOOST_PYTHON_MODULE(cpp)
{
    Py_Initialize();
    np::initialize();
    p::class_<Simulation_cpp>("Simulation_cpp", p::init<np::ndarray, double, int, double, double, double, double, unsigned int, unsigned int, int>())
        .def("set_h", &Simulation_cpp::set_h)
        .def("set_q", &Simulation_cpp::set_q)
        .def("set_jet_power", &Simulation_cpp::set_jet_power)
        .def("next_step", &Simulation_cpp::next_step)
        .def("get_h", &Simulation_cpp::get_h)
        .def("get_q", &Simulation_cpp::get_q)
        .def("get_time", &Simulation_cpp::get_time)
    ;
}


/*!
@file
Forward declares `boost::hana::mult`.

@copyright Louis Dionne 2013-2017
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
 */

#ifndef BOOST_HANA_FWD_MULT_HPP
#define BOOST_HANA_FWD_MULT_HPP

#include <boost/hana/config.hpp>
#include <boost/hana/core/when.hpp>

BOOST_HANA_NAMESPACE_BEGIN
    //! Associative operation of a `Ring`.
    //! @ingroup group-Ring
    //!
    //! @param x, y
    //! Two `Ring` elements to combine with the `Ring` binary operation.
    //!
    //!
    //! Cross-type version of the method
    //! --------------------------------
    //! The `mult` method is "overloaded" to handle distinct data types
    //! with certain properties. Specifically, `mult` is defined for
    //! _distinct_ data types `A` and `B` such that
    //! 1. `A` and `B` share a common data type `C`, as determined by the
    //!    `common` metafunction
    //! 2. `A`, `B` and `C` are all `Ring`s when taken individually
    //! 3. `to<C> : A -> B` and `to<C> : B -> C` are `Ring`-embeddings, as
    //!    determined by the `is_embedding` metafunction.
    //!
    //! The definition of `mult` for data types satisfying the above
    //! properties is obtained by setting
    //! @code
    //!     mult(x, y) = mult(to<C>(x), to<C>(y))
    //! @endcode
    //!
    //!
    //! Example
    //! -------
    //! @include example/mult.cpp
#ifdef BOOST_HANA_DOXYGEN_INVOKED
    constexpr auto mult = [](auto&& x, auto&& y) -> decltype(auto) {
        return tag-dispatched;
    };
#else
    template <typename T, typename U, typename = void>
    struct mult_impl : mult_impl<T, U, when<true>> { };

    struct mult_t {
        template <typename X, typename Y>
        constexpr decltype(auto) operator()(X&& x, Y&& y) const;
    };

    constexpr mult_t mult{};
#endif
BOOST_HANA_NAMESPACE_END

#endif // !BOOST_HANA_FWD_MULT_HPP