<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html><head>
        <title>A Proposal to add wide_int Class</title>
        <meta content="http://schemas.microsoft.com/intellisense/ie5" name="vs_targetSchema">
        <meta http-equiv="Content-Language" content="en-us">
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

        <style type="text/css">
            .addition { color: green; }
            .right { float:right; }
            .changed-deleted { background-color: #CFF0FC ; text-decoration: line-through; display: none; }
            .addition.changed-deleted { color: green; background-color: #CFF0FC ; text-decoration: line-through; text-decoration: black double line-through; display: none; }
            .changed-added { background-color: #CFF0FC ;}
            .notes { background-color: #80D080 ;}
            pre { line-height: 1.2; font-size: 10pt; margin-top: 25px; }
            .desc { margin-left: 35px; margin-top: 10px; padding:0; white-space: normal; }
            body {max-width: 1024px; margin-left: 25px;}
            .cppkeyword { color: blue; }
            .cppcomment { color: green; }
            .cppcomment > .cppkeyword{ color: green; }
            .cpptext { color: #2E8B57; }
        </style>
    </head>
    <body bgcolor="#ffffff">
        <address>Document number: P0539R3</address>
        <address>Project: Programming Language C++</address>
        <address>Audience: SG6 Numerics, Library Evolution</address>
        <address>&nbsp;</address>
        <address>Igor Klevanets &lt;<a href="mailto:cerevra@yandex.ru">cerevra@yandex.ru</a>&gt;, &lt;<a href="mailto:cerevra@yandex-team.ru">cerevra@yandex-team.ru</a>&gt;</address>
        <address>Antony Polukhin &lt;<a href="mailto:antoshkka@gmail.com">antoshkka@gmail.com</a>&gt;, &lt;<a href="mailto:antoshkka@yandex-team.ru">antoshkka@yandex-team.ru</a>&gt;</address>
        <address>&nbsp;</address>
        <address>Date: 2018-01-31</address>
        <h1>A Proposal to add wide_int Template Class</h1>

        <p class='changed-added'>Significant changes to <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0539r2.html">P0539R2</a> are marked with blue.<p>
        <p><input type="checkbox" id="show_deletions" onchange="show_hide_deleted()"> Show deleted lines from P0539R2.</p>
        <p class='notes'>Green lines are notes for the <b>editor</b> or for the <b>SG6</b> that must not be treated as part of the wording.</p>
        <h2>I. Introduction and Motivation</h2>
        <p>Current standard provides signed and unsigned int8_t, int16_t, int32_t, int64_t. It is usually enough for every day tasks, but sometimes appears a need in big numbers: for cryptography, IPv6, very big counters etc. Non-standard type __int128 which is provided by gcc and clang illuminates this need. But there is no cross-platform solution and no way to satisfy future needs in even more big numbers.</p>
        <p>This is an attempt to solve the problem in a generic way on a library level and provide wording for <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0104r0.html">P0104R0: Multi-Word Integer Operations and Types</a>.</p>
        <p>A proof of concept implementation available at: <a href="https://github.com/cerevra/int/tree/master/v3">https://github.com/cerevra/int/tree/master/v3</a>.
        </p>

        <h2>II. Changelog</h2>
        <p class='changed-added'>Differences with P0539R2:</p>
        <ul class='changed-added'>
            <li><strong>"Bits" won in the discussion "Words vs Bytes vs Bits" in Albuquerque</strong></li>
            <li>Changed "MachineWords" to "Bits"</li>
            <li>Interoperability with other types moved to a separate paper</li>
            <li>Removed <code>signedness</code> scoped enum</li>
        </ul>
        <p>Differences with P0539R1:</p>
        <ul>
            <li>Added a discussion on "Words vs Bytes vs Bits"</li>
        </ul>
        <p>Differences with P0539R0:</p>
        <ul>
            <li>Reworked the proposal for simpler integration with other Numerics proposals:
            <ul>
                <li>Added an interoperability section [numeric.interop]</li>
                <li><code>Arithmetic</code> and <code>Integral</code> concepts were moved to [numeric.requirements] as they seem widely useful</li>
                <li>Binary non-member operations that accept <code>Arithmetic</code> or <code>Integral</code> parameter were changed to accept two <code>Arithmetic</code> or <code>Integral</code> parameters respectively and moved to [numeric.interop]</li>
                <li><code>int128_t</code> and other aliases now depend on <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0102r0.html">P0102R0</a></li>
            </ul>
            </li>
            <li>Renamed <code>wide_int</code> to <code>wide_integer</code></li>
            <li><code>wide_integer</code> now uses machine words count as a template parameter, not bits count</li>
            <li>Removed not allowed type traits specializations</li>
            <li>Added <code>to_chars</code> and <code>from_chars</code></li>
        </ul>

        <h2 class="changed-added">III. Design and paper limitations</h2>
        <div class="changed-added">
        <p><code>wide_integer</code> is designed to be as close as possible to built-in integral types:</p>
        <ul>
            <li>it does not allocate memory</li>
            <li>it is a standard layout type</li>
            <li>it is trivially copyable</li>
            <li>it is trivially desctructible</li>
            <li>it is constexpr usable</li>
        </ul>
        <p><code>wide_integer</code> is <b>not</b> a metafunction. Such metafunctions are discussed in <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0102r0.html">P0102R0</a>.</p>
        <p><code>wide_integer</code> does <b>not</b> add <code>noexcept</code> to operations that have UB for built-in types. Operations that have UB traditionally are not marked
        with <code>noexcept</code> by LWG. Attempt to change that behavior may be done in separate paper.</p>

        <p>In this proposal we concentrate on the <code>wide_integer</code> class that uses machine words under the cover. Such implementations allow you to get best performance
        and leave behind some design questions, like "Is <code>(sizeof(wide_integer&lt;X&gt;)&nbsp;==&nbsp;X&nbsp;/&nbsp;CHAR_BITS)</code> or not?".</p>
        <p>However, we do not wish to shut the door close for extending the abilities of the <code>wide_integer</code> class. Some users may wish to see unit40_t, or unit48_t.</p>
        <p>We insist on <b>interface that allows specifying integers not representable by machine words count</b>. Such extensions of functionality may be discussed in separate papers.</p>
        </div>

        <h2 class='changed-deleted'>III. Discussion about the way to set the wide_integer size</h2>
        <div class='changed-deleted'>
        <p>In this proposal we would like to concentrate on the <code>wide_integer</code> class that uses machine words under the cover. Such implementations allow you to get best performance
        and leave behind some design questions, like "Is <code>(sizeof(wide_integer&lt;X&gt;)&nbsp;==&nbsp;X&nbsp;/&nbsp;CHAR_BITS)</code> or not?".</p>
        <p>However, we do not wish to shut the door close for extending the abilities of the <code>wide_integer</code> class. Some users may wish to see unit40_t, or unit48_t.</p>
        <p>We insist on <b>interface that allows specifying integers not representable by machine words count</b>. Such extensions of functionality may be discussed in separate papers.</p>

        <p class="notes"><b><i>[Note to SG6:</i></b> The "Words vs Bytes vs Bits" interface problem seems to rise very often. It may be worth discussing it in a bigger group
        or at least discuss it after the remaining parts of the paper are tentatively accepted. <i><b>- end note]</b></i></p>

        <p>There are several possible meanings of the first template argument of wide_integer:</p>
        <ul>
          <li>Number of machine words</li>
          <li>Number of bytes</li>
          <li>Number of bits</li>
        </ul>
        <p>Where number must be:</p>
        <ul>
          <li>Power of 2</li>
          <li>Or such as <code>sizeof(wide_integer)</code> is multiply of <code>sizeof(<i>machine word</i>)</code></li>
        </ul>

        <p>As was noted above, we would like to use <i>machine words</i> under the hood, but we would like to avoid any mention of <i>machine words</i> in the interface.
        Machine word is a strong restriction for interface, which does not allow to extend functionality in the future.</p>

        <p>"Power of 2" restriction seems over restrictive. If <i>machine word</i> is 32 bits users may wish to have <code>uint96_t</code>.
        Supporting such type is quite easy.</p>

        <p>So the actual choice can be <b>Bytes</b> or <b>Bits</b> where <code>sizeof(wide_integer)</code> is multiply of <code>sizeof(<i>machine word</i>)</code>.</p>
        <p>Pros and cons for Bits vs Bytes:</p>
        <ul>
          <li>x86 users are used to <b>Bits</b> due to wide usage of <code>&lt;cmath&gt;</code> aliases like <code>uint32_t</code>.</li>
          <li>Bytes hide the actual bits count. When x86 user specifies 16 bytes he probably wishes to get 128 <b>Bits</b>, not <code>CHAR_BITS * 16</code> bits.</li>
          <li><b>Bytes</b> are preferable for platforms that have <code>CHAR_BITS % 8 != 0</code>, because code with specified bits may not compile for such platform:
          <pre>void foo(wide_uint&lt;128&gt; ); // OK on x86, does not compile if CHAR_BITS == 9</pre>
          </li>
        </ul>
        <p>There was also an idea to provide a way for a user to replace the underlying type that represents machine word (allow to specify <code>unsigned int</code> or <code>long</code> or
        <code>long long</code>). Such idea seems to unnecessary complicate the interface and expose the internals of the <code>wide_integer</code> type. We assume that the decision must be done by
        the library implementor rather than by user.</p>
        </div>

        <h2>IV. Proposed wording</h2>

<h3>18.3.4 Class template numeric_limits<span class="right">[numeric.limits]</span></h3>
<p class="notes"><b><i>[Note to editor:</i></b> Add the following sentence after the sentence "Specializations shall be provided for each arithmetic type, both floating-point and integer, including bool." (first sentence in fourth paragraph in [numeric.limits]) <i><b>- end note]</b></i></p>
<p>Specializations shall be also provided for <code>wide_integer</code> type. <i>[Note:</i> If there is a built-in integral type <code>Integral</code> that has the same signedness and width as <code>wide_integer&lt;Bits, S&gt;</code>, then <code>numeric_limits&lt;wide_integer&lt;Bits, S&gt;&gt;</code> specialized in the same way as <code>numeric_limits&lt;Integral&gt;</code><i>- end note]</i> </p>

<div class="changed-deleted">
<h3>26.2 Definitions<span class="right">[numerics.defns]</span></h3>
<p class="notes"><b><i>[Note to editor:</i></b> Add the following paragraph to the end of [numerics.defns] <i><b>- end note]</b></i></p>
<p>Define <code>CT</code> as <code>common_type_t&lt;A, B&gt;</code>, where <code>A</code> and <code>B</code> are the types of the two function arguments.</p>


<h3>26.3 Numeric type requirements<span class="right">[numeric.requirements]</span></h3>
<p class="notes"><b><i>[Note to editor:</i></b> Add the following paragraphs to the end of [numeric.requirements] <i><b>- end note]</b></i></p>
<p>Functions that accept template parameters starting with <code>Arithmetic</code> shall not participate in overload resolution unless <code>std::numeric_limits&lt;Arithmetic&gt;::is_specialized</code> is true.</p>
<p>Functions that accept template parameters starting with <code>Integral</code> shall not participate in overload resolution unless <code>std::numeric_limits&lt;Integral&gt;::is_integer</code> is true.</p>


<h3>26.4 Numeric types interoperability<span class="right">[numeric.interop]</span></h3>


<p class="notes"><b><i>[Note to SG6:</i></b> This is an early attempt to make it possible for different numeric types to inter-operate. It works for <code>wide_integer<i> and </i>built-in types</code>, but this approach requires additional study and <code>common_type</code> fixes for new <code>Arithmetic</code> types. <i><b>- end note]</b></i></p>


<p>Following operators are defined for types <code>T</code> and <code>U</code> if <code>T</code> and <code>U</code> have a defined <code>common_type_t&lt;T, U&gt;</code> and satisfy the <code>Arithmetic</code> or <code>Integral</code> requirements from [numeric.requirements] <i>[Note:</i> Implementations are encouraged to provide optimized specializations of the following operators <i>- end note]</i>:</p>

<p class="notes"><b><i>[Note to SG6:</i></b> We may add to <code>Arithmetic</code> and <code>Integral</code> concepts additional requirement that <code>std::numeric_limits&lt;<i>Integral-or-Arithmetic</i>&gt;::is_interoprable</code> shall be true. In that case no user code will be broken even if user already added following operators. However this seems to be an overkill. <i><b>- end note]</b></i></p>


<pre>template&lt;typename Arithmetic1, typename Arithmetic2&gt;
  common_type_t&lt;Arithmetic1, Arithmetic2&gt;
  constexpr operator*(const Arithmetic1&amp; lhs, const Arithmetic2&amp; rhs);</pre>
<div class="desc"><i>Returns:</i> <code>CT(lhs) * CT(rhs)</code>.</div>

<pre>template&lt;typename Arithmetic1, typename Arithmetic2&gt;
  common_type_t&lt;Arithmetic1, Arithmetic2&gt;
  constexpr operator/(const Arithmetic1&amp; lhs, const Arithmetic2&amp; rhs);</pre>
<div class="desc"><i>Returns:</i> <code>CT(lhs) / CT(rhs)</code>.</div>

<pre>template&lt;typename Arithmetic1, typename Arithmetic2&gt;
  common_type_t&lt;Arithmetic1, Arithmetic2&gt;
  constexpr operator+(const Arithmetic1&amp; lhs, const Arithmetic2&amp; rhs);</pre>
<div class="desc"><i>Returns:</i> <code>CT(lhs) + CT(rhs)</code>.</div>

<pre>template&lt;typename Arithmetic1, typename Arithmetic2&gt;
  common_type_t&lt;Arithmetic1, Arithmetic2&gt;
  constexpr operator-(const Arithmetic1&amp; lhs, const Arithmetic2&amp; rhs);</pre>
<div class="desc"><i>Returns:</i> <code>CT(lhs) - CT(rhs)</code>.</div>

<pre>template&lt;typename Integral1, typename Integral2&gt;
  common_type_t&lt;Integral1, Integral2&gt;
  constexpr operator%(const Integral1&amp; lhs, const Integral2&amp; rhs);</pre>
<div class="desc"><i>Returns:</i> <code>CT(lhs) % CT(rhs)</code>.</div>

<pre>template&lt;typename Integral1, typename Integral2&gt;
  common_type_t&lt;Integral1, Integral2&gt;
  constexpr operator&amp;(const Integral1&amp; lhs, const Integral2&amp; rhs);</pre>
<div class="desc"><i>Returns:</i> <code>CT(lhs) &amp; CT(rhs)</code>.</div>

<pre>template&lt;typename Integral1, typename Integral2&gt;
  common_type_t&lt;Integral1, Integral2&gt;
  constexpr operator|(const Integral1&amp; lhs, const Integral2&amp; rhs);</pre>
<div class="desc"><i>Returns:</i> <code>CT(lhs) | CT(rhs)</code>.</div>

<pre>template&lt;typename Integral1, typename Integral2&gt;
  common_type_t&lt;Integral1, Integral2&gt;
  constexpr operator^(const Integral1&amp; lhs, const Integral2&amp; rhs);</pre>
<div class="desc"><i>Returns:</i> <code>CT(lhs) ^ CT(rhs)</code>.</div>

<pre>template&lt;typename Integral1, typename Integral2&gt;
  common_type_t&lt;Integral1, size_t&gt;
  constexpr operator&lt;&lt;(const Integral1&amp; lhs, const Integral2&amp; rhs);</pre>
<div class="desc"><i>Returns:</i> <code>common_type_t&lt;Integral1, size_t&gt;(lhs) &lt;&lt; static_cast&lt;size_t&gt;(rhs)</code>.</div>

<pre>template&lt;typename Integral1, typename Integral2&gt;
  common_type_t&lt;Integral1, size_t&gt;
  constexpr operator&gt;&gt;(const Integral1&amp; lhs, const Integral2&amp; rhs);</pre>
<div class="desc"><i>Returns:</i> <code>common_type_t&lt;Integral1, size_t&gt;(lhs) &gt;&gt; static_cast&lt;size_t&gt;(rhs)</code>.</div>

<pre>template&lt;typename Arithmetic1, typename Arithmetic2&gt;
  constexpr bool operator&lt;(const Arithmetic1&amp; lhs, const Arithmetic2&amp; rhs);</pre>
<div class="desc"><i>Returns:</i> <code>CT(lhs) &lt; CT(rhs)</code>.</div>

<pre>template&lt;typename Arithmetic1, typename Arithmetic2&gt;
  constexpr bool operator&gt;(const Arithmetic1&amp; lhs, const Arithmetic2&amp; rhs);</pre>
<div class="desc"><i>Returns:</i> <code>CT(lhs) &gt; CT(rhs)</code>.</div>

<pre>template&lt;typename Arithmetic1, typename Arithmetic2&gt;
  constexpr bool operator&lt;=(const Arithmetic1&amp; lhs, const Arithmetic2&amp; rhs);</pre>
<div class="desc"><i>Returns:</i> <code>CT(lhs) &lt;= CT(rhs)</code>.</div>

<pre>template&lt;typename Arithmetic1, typename Arithmetic2&gt;
  constexpr bool operator&gt;=(const Arithmetic1&amp; lhs, const Arithmetic2&amp; rhs);</pre>
<div class="desc"><i>Returns:</i> <code>CT(lhs) &gt;= CT(rhs)</code>.</div>

<pre>template&lt;typename Arithmetic1, typename Arithmetic2&gt;
  constexpr bool operator==(const Arithmetic1&amp; lhs, const Arithmetic2&amp; rhs);</pre>
<div class="desc"><i>Returns:</i> <code>CT(lhs) == CT(rhs)</code>.</div>

<pre>template&lt;typename Arithmetic1, typename Arithmetic2&gt;
  constexpr bool operator!=(const Arithmetic1&amp; lhs, const Arithmetic2&amp; rhs);</pre>
<div class="desc"><i>Returns:</i> <code>!(lhs == rhs)</code>.</div>


</div>







<h3>26.??.1 Header &lt;wide_integer&gt; synopsis<span class="right">[numeric.wide_integer.syn]</span></h3>
<pre>namespace std {
<span class="changed-deleted">
  enum class signedness {
      Unsigned,
      Signed
  };
</span>
  // 26.??.2 class template wide_integer
  template&lt;size_t Bits, typename S&gt; class wide_integer;

  // 26.??.?? type traits specializations
  template&lt;size_t Bits, typename S, size_t Bits2, typename S2&gt;
  struct common_type&lt;wide_integer&lt;Bits, S&gt;, wide_integer&lt;Bits2, S2&gt;&gt;;

  template&lt;size_t Bits, typename S, typename Arithmetic&gt;
  struct common_type&lt;wide_integer&lt;Bits, S&gt;, Arithmetic&gt;;

  template&lt;typename Arithmetic, size_t Bits, typename S&gt;
  struct common_type&lt;Arithmetic, wide_integer&lt;Bits, S&gt;&gt;
    : common_type&lt;wide_integer&lt;Bits, S&gt;, Arithmetic&gt;
  ;

  // 26.??.?? unary operations
  template&lt;size_t Bits, typename S&gt; constexpr wide_integer&lt;Bits, S&gt; operator~(const wide_integer&lt;Bits, S&gt;&amp; val) noexcept;
  template&lt;size_t Bits, typename S&gt; constexpr wide_integer&lt;Bits, S&gt; operator-(const wide_integer&lt;Bits, S&gt;&amp; val) noexcept(is_unsigned_v&lt;S&gt;);
  template&lt;size_t Bits, typename S&gt; constexpr wide_integer&lt;Bits, S&gt; operator+(const wide_integer&lt;Bits, S&gt;&amp; val) noexcept(is_unsigned_v&lt;S&gt;)<span class="changed-added"> noexcept</span>;

  // 26.??.?? binary operations
  template&lt;size_t Bits, typename S, size_t Bits2, typename S2&gt;
    common_type_t&lt;wide_integer&lt;Bits, S&gt;, wide_integer&lt;Bits2, S2&gt;&gt;
    constexpr operator*(const wide_integer&lt;Bits, S&gt;&amp; lhs, const wide_integer&lt;Bits2, S2&gt;&amp; rhs);

  template&lt;size_t Bits, typename S, size_t Bits2, typename S2&gt;
    common_type_t&lt;wide_integer&lt;Bits, S&gt;, wide_integer&lt;Bits2, S2&gt;&gt;
    constexpr operator/(const wide_integer&lt;Bits, S&gt;&amp; lhs, const wide_integer&lt;Bits2, S2&gt;&amp; rhs);

  template&lt;size_t Bits, typename S, size_t Bits2, typename S2&gt;
    common_type_t&lt;wide_integer&lt;Bits, S&gt;, wide_integer&lt;Bits2, S2&gt;&gt;
    constexpr operator+(const wide_integer&lt;Bits, S&gt;&amp; lhs, const wide_integer&lt;Bits2, S2&gt;&amp; rhs) noexcept(is_unsigned_v&lt;S&gt;);

  template&lt;size_t Bits, typename S, size_t Bits2, typename S2&gt;
    common_type_t&lt;wide_integer&lt;Bits, S&gt;, wide_integer&lt;Bits2, S2&gt;&gt;
    constexpr operator-(const wide_integer&lt;Bits, S&gt;&amp; lhs, const wide_integer&lt;Bits2, S2&gt;&amp; rhs) noexcept(is_unsigned_v&lt;S&gt;);

  template&lt;size_t Bits, typename S, size_t Bits2, typename S2&gt;
    common_type_t&lt;wide_integer&lt;Bits, S&gt;, wide_integer&lt;Bits2, S2&gt;&gt;
    constexpr operator%(const wide_integer&lt;Bits, S&gt;&amp; lhs, const wide_integer&lt;Bits2, S2&gt;&amp; rhs);

  template&lt;size_t Bits, typename S, size_t Bits2, typename S2&gt;
    common_type_t&lt;wide_integer&lt;Bits, S&gt;, wide_integer&lt;Bits2, S2&gt;&gt;
    constexpr operator&amp;(const wide_integer&lt;Bits, S&gt;&amp; lhs, const wide_integer&lt;Bits2, S2&gt;&amp; rhs) noexcept;

  template&lt;size_t Bits, typename S, size_t Bits2, typename S2&gt;
    common_type_t&lt;wide_integer&lt;Bits, S&gt;, wide_integer&lt;Bits2, S2&gt;&gt;
    constexpr operator|(const wide_integer&lt;Bits, S&gt;&amp; lhs, const wide_integer&lt;Bits2, S2&gt;&amp; rhs) noexcept;

  template&lt;size_t Bits, typename S, size_t Bits2, typename S2&gt;
    common_type_t&lt;wide_integer&lt;Bits, S&gt;, wide_integer&lt;Bits2, S2&gt;&gt;
    constexpr  operator^(const wide_integer&lt;Bits, S&gt;&amp; lhs, const wide_integer&lt;Bits2, S2&gt;&amp; rhs) noexcept;

  template&lt;size_t Bits, typename S&gt;
    common_type_t&lt;wide_integer&lt;Bits, S&gt;, size_t&gt;
    constexpr  operator&lt;&lt;(const wide_integer&lt;Bits, S&gt;&amp; lhs, size_t rhs);

  template&lt;size_t Bits, typename S&gt;
    common_type_t&lt;wide_integer&lt;Bits, S&gt;, size_t&gt;
    constexpr  operator&gt;&gt;(const wide_integer&lt;Bits, S&gt;&amp; lhs, size_t rhs);

  template&lt;size_t Bits, typename S, size_t Bits2, typename S2&gt;
    constexpr bool operator&lt;(const wide_integer&lt;Bits, S&gt;&amp; lhs, const wide_integer&lt;Bits2, S2&gt;&amp; rhs) noexcept;

  template&lt;size_t Bits, typename S, size_t Bits2, typename S2&gt;
    constexpr bool operator&gt;(const wide_integer&lt;Bits, S&gt;&amp; lhs, const wide_integer&lt;Bits2, S2&gt;&amp; rhs) noexcept;

  template&lt;size_t Bits, typename S, size_t Bits2, typename S2&gt;
    constexpr bool operator&lt;=(const wide_integer&lt;Bits, S&gt;&amp; lhs, const wide_integer&lt;Bits2, S2&gt;&amp; rhs) noexcept;

  template&lt;size_t Bits, typename S, size_t Bits2, typename S2&gt;
    constexpr bool operator&gt;=(const wide_integer&lt;Bits, S&gt;&amp; lhs, const wide_integer&lt;Bits2, S2&gt;&amp; rhs) noexcept;

  template&lt;size_t Bits, typename S, size_t Bits2, typename S2&gt;
    constexpr bool operator==(const wide_integer&lt;Bits, S&gt;&amp; lhs, const wide_integer&lt;Bits2, S2&gt;&amp; rhs) noexcept;

  template&lt;size_t Bits, typename S, size_t Bits2, typename S2&gt;
    constexpr bool operator!=(const wide_integer&lt;Bits, S&gt;&amp; lhs, const wide_integer&lt;Bits2, S2&gt;&amp; rhs) noexcept;

  // 26.??.?? numeric conversions
  template&lt;size_t Bits, typename S&gt; std::string to_string(const wide_integer&lt;Bits, S&gt;&amp; val);
  template&lt;size_t Bits, typename S&gt; std::wstring to_wstring(const wide_integer&lt;Bits, S&gt;&amp; val);

  // 26.??.?? iostream specializations
  template&lt;class Char, class Traits, size_t Bits, typename S&gt;
  basic_ostream&lt;Char, Traits&gt;&amp; operator&lt;&lt;(basic_ostream&lt;Char, Traits&gt;&amp; os, const wide_integer&lt;Bits, S&gt;&amp; val);

  template&lt;class Char, class Traits, size_t Bits, typename S&gt;
  basic_istream&lt;Char, Traits&gt;&amp; operator&gt;&gt;(basic_istream&lt;Char, Traits&gt;&amp; is, wide_integer&lt;Bits, S&gt;&amp; val) noexcept;

  // 26.??.?? hash support
  template&lt;class T&gt; struct hash;
  template&lt;size_t Bits, typename S&gt; struct hash&lt;wide_integer&lt;Bits, S&gt;&gt;;


  template &lt;size_t Bits, typename S&gt;
  to_chars_result to_chars(char* first,
                           char* last,
                           const wide_integer&lt;Bits, S&gt;&amp; value,
                           int base = 10);

  template &lt;size_t Bits, typename S&gt;
  from_chars_result from_chars(const char* first,
                               const char* last,
                               wide_integer&lt;Bits, S&gt;&amp; value,
                               int base = 10);

  template &lt;size_t Bits&gt;
  using wide_int = wide_integer&lt;Bits, signed&gt;;

  template &lt;size_t Bits&gt;
  using wide_uint = wide_integer&lt;Bits, unsigned&gt;
</pre>
<p class="notes"><b><i>[Note to SG6:</i></b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0102r0.html">P0102R0</a> 
proposal with <code>exact_2int</code>, <code>fast_2int</code>, <code>least_2int</code>,
<code>exact_2uint</code>, <code>fast_2uint</code>, <code>least_2uint</code> requires additional specializations for <code>wide_integer</code>.
 <i><b>- end note]</b></i></p>

<div class="changed-deleted">
<pre>
  // optional aliases
  using int128_t  = exact_2int&lt;128&gt;;      // <i>wide_int&lt;platform-specific&gt;</i> or <i>platform-specific build in type</i>
  using uint128_t = exact_2uint&lt;128&gt;;     // <i>wide_uint&lt;platform-specific&gt;</i> or <i>platform-specific build in type</i>

  using int256_t  = exact_2int&lt;256&gt;;      // <i>wide_int&lt;platform-specific&gt;</i> or <i>platform-specific build in type</i>
  using uint256_t = exact_2uint&lt;256&gt;;     // <i>wide_uint&lt;platform-specific&gt;</i> or <i>platform-specific build in type</i>

  using int512_t  = exact_2int&lt;512&gt;;      // <i>wide_int&lt;platform-specific&gt;</i> or <i>platform-specific build in type</i>
  using uint512_t = exact_2uint&lt;512&gt;;     // <i>wide_uint&lt;platform-specific&gt;</i> or <i>platform-specific build in type</i>


  // non optional aliases
  using int_fast128_t  = fast_2int&lt;128&gt;;   // wide_int&lt;<i>platform-specific</i>&gt;<span class="changed-added"> or <i>platform-specific build in type</i></span>
  using uint_fast128_t = fast_2uint&lt;128&gt;;  // wide_uint&lt;<i>platform-specific</i>&gt;<span class="changed-added"> or <i>platform-specific build in type</i></span>

  using int_fast256_t  = fast_2int&lt;256&gt;;   // wide_int&lt;<i>platform-specific</i>&gt;<span class="changed-added"> or <i>platform-specific build in type</i></span>
  using uint_fast256_t = fast_2uint&lt;256&gt;;  // wide_uint&lt;<i>platform-specific</i>&gt;<span class="changed-added"> or <i>platform-specific build in type</i></span>

  using int_fast512_t  = fast_2int&lt;512&gt;;   // wide_int&lt;<i>platform-specific</i>&gt;<span class="changed-added"> or <i>platform-specific build in type</i></span>
  using uint_fast512_t = fast_2uint&lt;512&gt;;  // wide_uint&lt;<i>platform-specific</i>&gt;<span class="changed-added"> or <i>platform-specific build in type</i></span>


  using int_least128_t  = least_2int&lt;128&gt;;   // wide_int&lt;<i>platform-specific</i>&gt;<span class="changed-added"> or <i>platform-specific build in type</i></span>
  using uint_least128_t = least_2uint&lt;128&gt;;  // wide_uint&lt;<i>platform-specific</i>&gt;<span class="changed-added"> or <i>platform-specific build in type</i></span>

  using int_least256_t  = least_2int&lt;256&gt;;   // wide_int&lt;<i>platform-specific</i>&gt;<span class="changed-added"> or <i>platform-specific build in type</i></span>
  using uint_least256_t = least_2uint&lt;256&gt;;  // wide_uint&lt;<i>platform-specific</i>&gt;<span class="changed-added"> or <i>platform-specific build in type</i></span>

  using int_least512_t  = least_2int&lt;512&gt;;   // wide_int&lt;<i>platform-specific</i>&gt;<span class="changed-added"> or <i>platform-specific build in type</i></span>
  using uint_least512_t = least_2uint&lt;512&gt;;  // wide_uint&lt;<i>platform-specific</i>&gt;<span class="changed-added"> or <i>platform-specific build in type</i></span>
</pre>
</div>

<pre>
  // optional literals
  inline namespace literals {
  inline namespace wide_int_literals {

  constexpr wide_int&lt;128&gt; operator &quot;&quot; _int128(const char*);
  constexpr wide_int&lt;256&gt; operator &quot;&quot; _int256(const char*);
  constexpr wide_int&lt;512&gt; operator &quot;&quot; _int512(const char*);
  constexpr wide_uint&lt;128&gt; operator &quot;&quot; _uint128(const char*);
  constexpr wide_uint&lt;256&gt; operator &quot;&quot; _uint256(const char*);
  constexpr wide_uint&lt;512&gt; operator &quot;&quot; _uint512(const char*);

  } // namespace wide_int_literals
  } // namespace literals
}
</pre>
<p>The header &lt;wide_integer&gt; defines class template <code>wide_integer</code> and a set of operators for representing and manipulating integers of specified width.</p><pre>[Example:
    using int128_t = wide_int&lt;128&gt;;
    constexpr int128_t c = std::numeric_limits&lt;int128_t&gt;::min();
    static_assert(c == 0x80000000000000000000000000000000_uint128);

    int256_t a = 13;
    a += 0xFF;
    a *= 2.0;
    a -= 12_int128;
    assert(a &gt; 0);
]</pre>


<h3>26.??.2 Template class wide_integer overview<span class="right">[numeric.wide_integer.overview]</span></h3>
<pre>namespace std {
  template&lt;size_t Bits, typename S&gt;
  class wide_integer {
  public:
    // 26.??.2.?? construct:
    constexpr wide_integer() noexcept = default;
    constexpr wide_integer(const wide_integer&lt;Bits, S&gt;&amp; ) noexcept = default;
    template&lt;typename Arithmetic&gt; constexpr wide_integer(const Arithmetic&amp; other) noexcept;
    template&lt;size_t Bits2, typename S2&gt; constexpr wide_integer(const wide_integer&lt;Bits2, S2&gt;&amp; other) noexcept;

    // 26.??.2.?? assignment:
    constexpr wide_integer&lt;Bits, S&gt;&amp; operator=(const wide_integer&lt;Bits, S&gt;&amp; ) noexcept = default;
    template&lt;typename Arithmetic&gt;
    constexpr wide_integer&lt;Bits, S&gt;&amp; operator=(const Arithmetic&amp; other) noexcept;
    template&lt;size_t Bits2, typename S2&gt;
    constexpr wide_integer&lt;Bits, S&gt;&amp; operator=(const wide_integer&lt;Bits2, S2&gt;&amp; other) noexcept;

    // 26.??.2.?? compound assignment:
    template&lt;typename Arithmetic&gt;
    constexpr wide_integer&lt;Bits, S&gt;&amp; operator*=(const Arithmetic&amp;);
    template&lt;size_t Bits2, typename S2&gt;
    constexpr wide_integer&lt;Bits, S&gt;&amp; operator*=(const wide_integer&lt;Bits2, S2&gt;&amp;);

    template&lt;typename Arithmetic&gt;
    constexpr wide_integer&lt;Bits, S&gt;&amp; operator/=(const Arithmetic&amp;);
    template&lt;size_t Bits2, typename S2&gt;
    constexpr wide_integer&lt;Bits, S&gt;&amp; operator/=(const wide_integer&lt;Bits2, S2&gt;&amp;);

    template&lt;typename Arithmetic&gt;
    constexpr wide_integer&lt;Bits, S&gt;&amp; operator+=(const Arithmetic&amp;) noexcept(is_unsigned_v&lt;S&gt;);
    template&lt;size_t Bits2, typename S2&gt;
    constexpr wide_integer&lt;Bits, S&gt;&amp; operator+=(const wide_integer&lt;Bits2, S2&gt;&amp;) noexcept(is_unsigned_v&lt;S&gt;);

    template&lt;typename Arithmetic&gt;
    constexpr wide_integer&lt;Bits, S&gt;&amp; operator-=(const Arithmetic&amp;) noexcept(is_unsigned_v&lt;S&gt;);
    template&lt;size_t Bits2, typename S2&gt;
    constexpr wide_integer&lt;Bits, S&gt;&amp; operator-=(const wide_integer&lt;Bits2, S2&gt;&amp;) noexcept(is_unsigned_v&lt;S&gt;);

    template&lt;typename Integral&gt;
    constexpr wide_integer&lt;Bits, S&gt;&amp; operator%=(const Integral&amp;);
    template&lt;size_t Bits2, typename S2&gt;
    constexpr wide_integer&lt;Bits, S&gt;&amp; operator%=(const wide_integer&lt;Bits2, S2&gt;&amp;);

    template&lt;typename Integral&gt;
    constexpr wide_integer&lt;Bits, S&gt;&amp; operator&amp;=(const Integral&amp;) noexcept;
    template&lt;size_t Bits2, typename S2&gt;
    constexpr wide_integer&lt;Bits, S&gt;&amp; operator&amp;=(const wide_integer&lt;Bits2, S2&gt;&amp;) noexcept;

    template&lt;typename Integral&gt;
    constexpr wide_integer&lt;Bits, S&gt;&amp; operator|=(const Integral&amp;) noexcept;
    template&lt;size_t Bits2, typename S2&gt;
    constexpr wide_integer&lt;Bits, S&gt;&amp; operator|=(const wide_integer&lt;Bits2, S2&gt;&amp;) noexcept;

    template&lt;typename Integral&gt;
    constexpr wide_integer&lt;Bits, S&gt;&amp; operator^=(const Integral&amp;) noexcept;
    template&lt;size_t Bits2, typename S2&gt;
    constexpr wide_integer&lt;Bits, S&gt;&amp; operator^=(const wide_integer&lt;Bits2, S2&gt;&amp;) noexcept;

    template&lt;typename Integral&gt;
    constexpr wide_integer&lt;Bits, S&gt;&amp; operator&lt;&lt;=(const Integral&amp;);
    template&lt;size_t Bits2, typename S2&gt;
    constexpr wide_integer&lt;Bits, S&gt;&amp; operator&lt;&lt;=(const wide_integer&lt;Bits2, S2&gt;&amp;);

    template&lt;typename Integral&gt;
    constexpr wide_integer&lt;Bits, S&gt;&amp; operator&gt;&gt;=(const Integral&amp;) noexcept;
    template&lt;size_t Bits2, typename S2&gt;
    constexpr wide_integer&lt;Bits, S&gt;&amp; operator&gt;&gt;=(const wide_integer&lt;Bits2, S2&gt;&amp;) noexcept;

    constexpr wide_integer&lt;Bits, S&gt;&amp; operator++() noexcept(is_unsigned_v&lt;S&gt;);
    constexpr wide_integer&lt;Bits, S&gt; operator++(int) noexcept(is_unsigned_v&lt;S&gt;);
    constexpr wide_integer&lt;Bits, S&gt;&amp; operator--() noexcept(is_unsigned_v&lt;S&gt;);
    constexpr wide_integer&lt;Bits, S&gt; operator--(int) noexcept(is_unsigned_v&lt;S&gt;);

    // 26.??.2.?? observers:
    template &lt;typename Arithmetic&gt; constexpr operator Arithmetic() const noexcept;
    constexpr explicit operator bool() const noexcept;

  private:
    byte data[Bits / CHAR_BITS]; // exposition only
  };
}</pre>
<p>The class template <code>wide_integer&lt;size_t Bits, typename S&gt;</code> is a trivial standard layout class that behaves as an integer type
of a compile time specified bitness.</p>
<p>Template parameter <code>Bits</code> specifies exact <i>bits</i> count to store the integer value. <span class="changed-added"><code>Bits % (sizeof(int) * CHAR_BITS)</code> is eqaul to 0.</span>
<code>sizeof(wide_integer&lt;Bits, unsigned&gt;)</code> and <code>sizeof(wide_integer&lt;Bits, signed&gt;)</code> are required to
be equal to <code>Bits * CHAR_BITS</code>.</p>
<p>Template parameter <code>S</code> specifies signedness of the stored integer value<span class="changed-added"> and is either <code>signed</code> or <code>unsigned</code></span>.</p>

<h4>26.??.2.?? wide_integer constructors <span class="right">[numeric.wide_integer.cons]</span></h4>
<pre>constexpr wide_integer() noexcept = default;</pre>
<div class="desc"><i>Effects:</i> A Constructs an object with undefined value.</div>

<pre>template&lt;typename Arithmetic&gt; constexpr wide_integer(const Arithmetic&amp; other) noexcept;</pre>
<div class="desc"><i>Effects:</i> Constructs an object from <code>other</code> using the integral conversion rules [conv.integral].</div>

<pre>template&lt;size_t Bits2, typename S2&gt; constexpr wide_integer(const wide_integer&lt;Bits2, S2&gt;&amp; other) noexcept;</pre>
<div class="desc"><i>Effects:</i> Constructs an object from <code>other</code> using the integral conversion rules [conv.integral].</div>

<h4>26.??.2.?? wide_integer assignments <span class="right">[numeric.wide_integer.assign]</span></h4>
<pre>template&lt;typename Arithmetic&gt;
constexpr wide_integer&lt;Bits, S&gt;&amp; operator=(const Arithmetic&amp; other) noexcept;</pre>
<div class="desc"><i>Effects:</i> Constructs an object from <code>other</code> using the integral conversion rules [conv.integral].</div>

<pre>template&lt;size_t Bits2, typename S2&gt;
constexpr wide_integer&lt;Bits, S&gt;&amp; operator=(const wide_integer&lt;Bits2, S2&gt;&amp; other) noexcept;</pre>
<div class="desc"><i>Effects:</i> Constructs an object from <code>other</code> using the integral conversion rules [conv.integral].</div>

<h4>26.??.2.?? wide_integer compound assignments <span class="right">[numeric.wide_integer.cassign]</span></h4>
<pre>template&lt;size_t Bits2, typename S2&gt; constexpr wide_integer&lt;Bits, S&gt;&amp; operator*=(const wide_integer&lt;Bits2, S2&gt;&amp;);
template&lt;size_t Bits2, typename S2&gt; constexpr wide_integer&lt;Bits, S&gt;&amp; operator/=(const wide_integer&lt;Bits2, S2&gt;&amp;);
template&lt;size_t Bits2, typename S2&gt; constexpr wide_integer&lt;Bits, S&gt;&amp; operator+=(const wide_integer&lt;Bits2, S2&gt;&amp;) noexcept(is_unsigned_v&lt;S&gt;);
template&lt;size_t Bits2, typename S2&gt; constexpr wide_integer&lt;Bits, S&gt;&amp; operator-=(const wide_integer&lt;Bits2, S2&gt;&amp;) noexcept(is_unsigned_v&lt;S&gt;);
template&lt;size_t Bits2, typename S2&gt; constexpr wide_integer&lt;Bits, S&gt;&amp; operator%=(const wide_integer&lt;Bits2, S2&gt;&amp;);
template&lt;size_t Bits2, typename S2&gt; constexpr wide_integer&lt;Bits, S&gt;&amp; operator&amp;=(const wide_integer&lt;Bits2, S2&gt;&amp;) noexcept;
template&lt;size_t Bits2, typename S2&gt; constexpr wide_integer&lt;Bits, S&gt;&amp; operator|=(const wide_integer&lt;Bits2, S2&gt;&amp;) noexcept;
template&lt;size_t Bits2, typename S2&gt; constexpr wide_integer&lt;Bits, S&gt;&amp; operator^=(const wide_integer&lt;Bits2, S2&gt;&amp;) noexcept;
template&lt;size_t Bits2, typename S2&gt; constexpr wide_integer&lt;Bits, S&gt;&amp; operator&lt;&lt;=(const wide_integer&lt;Bits2, S2&gt;&amp;);
template&lt;size_t Bits2, typename S2&gt; constexpr wide_integer&lt;Bits, S&gt;&amp; operator&gt;&gt;=(const wide_integer&lt;Bits2, S2&gt;&amp;) noexcept;
constexpr wide_integer&lt;Bits, S&gt;&amp; operator++() noexcept(is_unsigned_v&lt;S&gt;);
constexpr wide_integer&lt;Bits, S&gt; operator++(int) noexcept(is_unsigned_v&lt;S&gt;);
constexpr wide_integer&lt;Bits, S&gt;&amp; operator--() noexcept(is_unsigned_v&lt;S&gt;);
constexpr wide_integer&lt;Bits, S&gt; operator--(int) noexcept(is_unsigned_v&lt;S&gt;);</pre>
<div class="desc"><i>Effects:</i> Behavior of the above operators is similar to operators for built-in integral types.</div>

<pre>template&lt;typename Arithmetic&gt; constexpr wide_integer&lt;Bits, S&gt;&amp; operator*=(const Arithmetic&amp;);
template&lt;typename Arithmetic&gt; constexpr wide_integer&lt;Bits, S&gt;&amp; operator/=(const Arithmetic&amp;);
template&lt;typename Arithmetic&gt; constexpr wide_integer&lt;Bits, S&gt;&amp; operator+=(const Arithmetic&amp;) noexcept(is_unsigned_v&lt;S&gt;);
template&lt;typename Arithmetic&gt; constexpr wide_integer&lt;Bits, S&gt;&amp; operator-=(const Arithmetic&amp;) noexcept(is_unsigned_v&lt;S&gt;);</pre>
<div class="desc"><i>Effects:</i> As if an object <code>wi</code> of type <code>wide_integer&lt;Bits, S&gt;</code> was created from input value and the corresponding operator was called for <code>*this</code> and the <code>wi</code>.</div>

<pre>template&lt;typename Integral&gt; constexpr wide_integer&lt;Bits, S&gt;&amp; operator%=(const Integral&amp;);
template&lt;typename Integral&gt; constexpr wide_integer&lt;Bits, S&gt;&amp; operator&amp;=(const Integral&amp;) noexcept;
template&lt;typename Integral&gt; constexpr wide_integer&lt;Bits, S&gt;&amp; operator|=(const Integral&amp;) noexcept;
template&lt;typename Integral&gt; constexpr wide_integer&lt;Bits, S&gt;&amp; operator^=(const Integral&amp;) noexcept;
template&lt;typename Integral&gt; constexpr wide_integer&lt;Bits, S&gt;&amp; operator&lt;&lt;=(const Integral&amp;);
template&lt;typename Integral&gt; constexpr wide_integer&lt;Bits, S&gt;&amp; operator&gt;&gt;=(const Integral&amp;) noexcept;</pre>
<div class="desc"><i>Effects:</i> As if an object <code>wi</code> of type <code>wide_integer&lt;Bits, S&gt;</code> was created from input value and the corresponding operator was called for <code>*this</code> and the <code>wi</code>.</div>


<h4>26.??.2.?? wide_integer observers <span class="right">[numeric.wide_integer.observers]</span></h4>
<pre>template &lt;typename Arithmetic&gt; constexpr operator Arithmetic() const noexcept;</pre>
<div class="desc"><i>Returns:</i> If <code>Arithmetic</code> type is an integral type then it is constructed from <code>*this</code> using the integral conversion rules [conv.integral]. Otherwise <code>Arithmetic</code> is constructed from <code>*this</code> using the floating-integral conversion rules [conv.fpint].</div>

<pre>constexpr explicit operator bool() const noexcept;</pre>
<div class="desc"><i>Returns:</i> <code>true</code> if <code>*this</code> is not equal to 0.</div>


<h3>26.??.?? Specializations of common_type <span class="right">[numeric.wide_integer.traits.specializations]</span></h3>

<pre>template&lt;size_t Bits, typename S, size_t Bits2, typename S2&gt;
struct common_type&lt;wide_integer&lt;Bits, S&gt;, wide_integer&lt;Bits2, S2&gt;&gt; {
  using type = wide_integer&lt;max(Bits, Bits2), <i>see below</i>&gt;;
};</pre>

<p>The signed template parameter indicated by this specialization is following:</p>
<ul>
  <li><code>(is_signed_v&lt;S&gt; &amp;&amp; is_signed_v&lt;S2&gt; ? signed : unsigned)</code> if <code>Bits == Bits2</code></li>
  <li><code>S</code> if <code>Bits > Bits2</code></li>
  <li><code>S2</code> otherwise</li>
</ul>
<p><i>[Note: </i> <code>common_type</code> follows the <i>usual arithmetic conversions</i> design. <i>- end note]</i></p>

<p class="notes"><b><i>[Note to SG6:</i></b> <code>common_type</code> attempts to follow the <i>usual arithmetic conversions</i> design here for interoperability between different numeric types. Following two specializations must be moved to a more generic place and enriched with usual arithmetic conversion rules for <b>all the other</b> numeric classes that specialize <code>std::numeric_limits</code><i><b>- end note]</b></i></p>
<pre>template&lt;size_t Bits, typename S, typename Arithmetic&gt;
struct common_type&lt;wide_integer&lt;Bits, S&gt;, Arithmetic&gt; {
  using type = <i>see below</i>;
};</pre>

<pre>template&lt;typename Arithmetic, size_t Bits, typename S&gt;
struct common_type&lt;Arithmetic, wide_integer&lt;Bits, S&gt;&gt;
  : common_type&lt;wide_integer&lt;Bits, S&gt;, Arithmetic&gt;;
</pre>

<p>The member typedef <code>type</code> is following:</p>
<ul>
  <li><code>Arithmetic</code> if <code>numeric_limits&lt;Arithmetic&gt;::is_integer</code> is <code>false</code></li>
  <li><code>wide_integer&lt;Bits, S&gt;</code> if <code>sizeof(wide_integer&lt;Bits, S&gt;) &gt; sizeof(Arithmetic)</code></li>
  <li><code>Arithmetic</code> if <code>sizeof(wide_integer&lt;Bits, S&gt;) &lt; sizeof(Arithmetic)</code></li>
  <li><code>Arithmetic</code> if <code>sizeof(wide_integer&lt;Bits, S&gt;) == sizeof(Arithmetic) &amp;&amp; is_signed_v&lt;S&gt;</code></li>
  <li><code>Arithmetic</code> if <code>sizeof(wide_integer&lt;Bits, S&gt;) == sizeof(Arithmetic) &amp;&amp; numeric_limits&lt;wide_integer&lt;Bits, S&gt;&gt;::is_signed == numeric_limits&lt;Arithmetic&gt;::is_signed</code></li>
  <li><code>wide_integer&lt;Bits, S&gt;</code> otherwise</li>
</ul>

<h3>26.??.?? Unary operators <span class="right">[numeric.wide_integer.unary_ops]</span></h3>
<pre>template&lt;size_t Bits, typename S&gt; constexpr wide_integer&lt;Bits, S&gt; operator~(const wide_integer&lt;Bits, S&gt;&amp; val) noexcept;</pre>
<div class="desc"><i>Returns:</i> value with inverted significant bits of <code>val</code>.</div>

<pre>template&lt;size_t Bits, typename S&gt; constexpr wide_integer&lt;Bits, S&gt; operator-(const wide_integer&lt;Bits, S&gt;&amp; val) noexcept(is_unsigned_v&lt;S&gt;);</pre>
<div class="desc"><i>Returns:</i> <code>val *= -1</code> if <code>S</code> is true, otherwise the result is unspecified.</div>

<pre>template&lt;size_t Bits, typename S&gt; constexpr wide_integer&lt;Bits, S&gt; operator+(const wide_integer&lt;Bits, S&gt;&amp; val) noexcept(is_unsigned_v&lt;S&gt;);</pre>
<div class="desc"><i>Returns:</i> <code>val</code>.</div>

<h3>26.??.?? Binary operators <span class="right">[numeric.wide_integer.binary_ops]</span></h3>
<p>In the function descriptions that follow, <code>CT</code> represents <code>common_type_t&lt;A, B&gt;</code>, where <code>A</code> and <code>B</code> are the types of the two arguments to the function.</p>

<pre>template&lt;size_t Bits, typename S, size_t Bits2, typename S2&gt;
  common_type_t&lt;wide_integer&lt;Bits, S&gt;, wide_integer&lt;Bits2, S2&gt;&gt;
  constexpr operator*(const wide_integer&lt;Bits, S&gt;&amp; lhs, const wide_integer&lt;Bits2, S2&gt;&amp; rhs);</pre>
<div class="desc"><i>Returns:</i> <code>CT(lhs) *= rhs</code>.</div>

<pre>template&lt;size_t Bits, typename S, size_t Bits2, typename S2&gt;
  common_type_t&lt;wide_integer&lt;Bits, S&gt;, wide_integer&lt;Bits2, S2&gt;&gt;
  constexpr operator/(const wide_integer&lt;Bits, S&gt;&amp; lhs, const wide_integer&lt;Bits2, S2&gt;&amp; rhs);</pre>
<div class="desc"><i>Returns:</i> <code>CT(lhs) /= rhs</code>.</div>


<pre>template&lt;size_t Bits, typename S, size_t Bits2, typename S2&gt;
  common_type_t&lt;wide_integer&lt;Bits, S&gt;, wide_integer&lt;Bits2, S2&gt;&gt;
  constexpr operator+(const wide_integer&lt;Bits, S&gt;&amp; lhs, const wide_integer&lt;Bits2, S2&gt;&amp; rhs) noexcept(is_unsigned_v&lt;S&gt;);</pre>
<div class="desc"><i>Returns:</i> <code>CT(lhs) += rhs</code>.</div>


<pre>template&lt;size_t Bits, typename S, size_t Bits2, typename S2&gt;
  common_type_t&lt;wide_integer&lt;Bits, S&gt;, wide_integer&lt;Bits2, S2&gt;&gt;
  constexpr operator-(const wide_integer&lt;Bits, S&gt;&amp; lhs, const wide_integer&lt;Bits2, S2&gt;&amp; rhs) noexcept(is_unsigned_v&lt;S&gt;);</pre>
<div class="desc"><i>Returns:</i> <code>CT(lhs) -= rhs</code>.</div>


<pre>template&lt;size_t Bits, typename S, size_t Bits2, typename S2&gt;
  common_type_t&lt;wide_integer&lt;Bits, S&gt;, wide_integer&lt;Bits2, S2&gt;&gt;
  constexpr operator%(const wide_integer&lt;Bits, S&gt;&amp; lhs, const wide_integer&lt;Bits2, S2&gt;&amp; rhs);</pre>
<div class="desc"><i>Returns:</i> <code>CT(lhs) %= rhs</code>.</div>


<pre>template&lt;size_t Bits, typename S, size_t Bits2, typename S2&gt;
  common_type_t&lt;wide_integer&lt;Bits, S&gt;, wide_integer&lt;Bits2, S2&gt;&gt;
  constexpr operator&amp;(const wide_integer&lt;Bits, S&gt;&amp; lhs, const wide_integer&lt;Bits2, S2&gt;&amp; rhs) noexcept;</pre>
<div class="desc"><i>Returns:</i> <code>CT(lhs) &amp;= rhs</code>.</div>

<pre>template&lt;size_t Bits, typename S, size_t Bits2, typename S2&gt;
  common_type_t&lt;wide_integer&lt;Bits, S&gt;, wide_integer&lt;Bits2, S2&gt;&gt;
  constexpr operator|(const wide_integer&lt;Bits, S&gt;&amp; lhs, const wide_integer&lt;Bits2, S2&gt;&amp; rhs) noexcept;</pre>
<div class="desc"><i>Returns:</i> <code>CT(lhs) |= rhs</code>.</div>

<pre>template&lt;size_t Bits, typename S, size_t Bits2, typename S2&gt;
  common_type_t&lt;wide_integer&lt;Bits, S&gt;, wide_integer&lt;Bits2, S2&gt;&gt;
  constexpr  operator^(const wide_integer&lt;Bits, S&gt;&amp; lhs, const wide_integer&lt;Bits2, S2&gt;&amp; rhs) noexcept;</pre>
<div class="desc"><i>Returns:</i> <code>CT(lhs) ^= rhs</code>.</div>

<pre>template&lt;size_t Bits, typename S&gt;
  common_type_t&lt;wide_integer&lt;Bits, S&gt;, size_t&gt;
  constexpr operator&lt;&lt;(const wide_integer&lt;Bits, S&gt;&amp; lhs, size_t rhs);</pre>
<div class="desc"><i>Returns:</i> <code>CT(lhs) &lt;&lt;= rhs</code>.</div>


<pre>template&lt;size_t Bits, typename S&gt;
  common_type_t&lt;wide_integer&lt;Bits, S&gt;, size_t&gt;
  constexpr operator&gt;&gt;(const wide_integer&lt;Bits, S&gt;&amp; lhs, size_t rhs) noexcept;</pre>
<div class="desc"><i>Returns:</i> <code>CT(lhs) &gt;&gt;= rhs</code>.</div>




<pre>template&lt;size_t Bits, typename S, size_t Bits2, typename S2&gt;
  constexpr bool operator&lt;(const wide_integer&lt;Bits, S&gt;&amp; lhs, const wide_integer&lt;Bits2, S2&gt;&amp; rhs) noexcept;</pre>
<div class="desc"><i>Returns:</i> <code>true</code> if value of <code>CT(lhs)</code> is less than the value of <code>CT(rhs)</code>.</div>


<pre>template&lt;size_t Bits, typename S, size_t Bits2, typename S2&gt;
  constexpr bool operator&gt;(const wide_integer&lt;Bits, S&gt;&amp; lhs, const wide_integer&lt;Bits2, S2&gt;&amp; rhs) noexcept;</pre>
<div class="desc"><i>Returns:</i> <code>true</code> if value of <code>CT(lhs)</code> is greater than the value of <code>CT(rhs)</code>.</div>


<pre>template&lt;size_t Bits, typename S, size_t Bits2, typename S2&gt;
  constexpr bool operator&lt;=(const wide_integer&lt;Bits, S&gt;&amp; lhs, const wide_integer&lt;Bits2, S2&gt;&amp; rhs) noexcept;</pre>
<div class="desc"><i>Returns:</i> <code>true</code> if value of <code>CT(lhs)</code> is equal or less than the value of <code>CT(rhs)</code>.</div>


<pre>template&lt;size_t Bits, typename S, size_t Bits2, typename S2&gt;
  constexpr bool operator&gt;=(const wide_integer&lt;Bits, S&gt;&amp; lhs, const wide_integer&lt;Bits2, S2&gt;&amp; rhs) noexcept;</pre>
<div class="desc"><i>Returns:</i> <code>true</code> if value of <code>CT(lhs)</code> is equal or greater than the value of <code>CT(rhs)</code>.</div>


<pre>template&lt;size_t Bits, typename S, size_t Bits2, typename S2&gt;
  constexpr bool operator==(const wide_integer&lt;Bits, S&gt;&amp; lhs, const wide_integer&lt;Bits2, S2&gt;&amp; rhs) noexcept;</pre>
<div class="desc"><i>Returns:</i> <code>true</code> if significant bits of <code>CT(lhs)</code> and <code>CT(rhs)</code> are the same.</div>

<pre>template&lt;size_t Bits, typename S, size_t Bits2, typename S2&gt;
  constexpr bool operator!=(const wide_integer&lt;Bits, S&gt;&amp; lhs, const wide_integer&lt;Bits2, S2&gt;&amp; rhs) noexcept;</pre>
<div class="desc"><i>Returns:</i> <code>!(CT(lhs) == CT(rhs))</code>.</div>



<h3>26.??.?? Numeric conversions <span class="right">[numeric.wide_integer.conversions]</span></h3>
<pre>template&lt;size_t Bits, typename S&gt; std::string to_string(const wide_integer&lt;Bits, S&gt;&amp; val);
template&lt;size_t Bits, typename S&gt; std::wstring to_wstring(const wide_integer&lt;Bits, S&gt;&amp; val);</pre>
<div class="desc"><i>Returns:</i> Each function returns an object holding the character representation of the value of its argument. All the significant bits of the argument are outputed as a signed decimal in the style <code>[-]dddd</code>.</div>

<div>
<pre>
template &lt;size_t Bits, typename S&gt;
to_chars_result to_chars(char* first,
                       char* last,
                       const wide_integer&lt;Bits, S&gt;&amp; value,
                       int base = 10);
</pre>
<p>Behavior of <code>wide_integer</code> overload is subject to the usual rules of primitive numeric output conversion functions [utility.to.chars].</p>

<pre>template &lt;size_t Bits, typename S&gt;
from_chars_result from_chars(const char* first,
                           const char* last,
                           wide_integer&lt;Bits, S&gt;&amp; value,
                           int base = 10);
</pre>
<p>Behavior of <code>wide_integer</code> overload is subject to the usual rules of primitive numeric input conversion functions [utility.from.chars].</p>
</div>

<h3>26.??.?? iostream specializations <span class="right">[numeric.wide_integer.io]</span></h3>
<pre>template&lt;class Char, class Traits, size_t Bits, typename S&gt;
basic_ostream&lt;Char, Traits&gt;&amp; operator&lt;&lt;(basic_ostream&lt;Char, Traits&gt;&amp; os, const wide_integer&lt;Bits, S&gt;&amp; val);</pre>
<div class="desc"><i>Effects:</i> As if by: <code>os &lt;&lt; to_string(val)</code>.</div>
<div class="desc"><i>Returns:</i> <code>os</code>.</div>


<pre>template&lt;class Char, class Traits, size_t Bits, typename S&gt;
basic_istream&lt;Char, Traits&gt;&amp; operator&gt;&gt;(basic_istream&lt;Char, Traits&gt;&amp; is, wide_integer&lt;Bits, S&gt;&amp; val);</pre>
<div class="desc"><i>Effects:</i> Extracts a <code>wide_integer</code> that is represented as a decimal number in the <code>is</code>. If bad input is encountered, calls <code>is.setstate(ios_base::failbit)</code> (which may throw <code>ios::failure</code> ([iostate.flags])).</div>
<div class="desc"><i>Returns:</i> <code>is</code>.</div>


<h3>26.??.?? Hash support <span class="right">[numeric.wide_integer.hash]</span></h3>
<pre>template&lt;size_t Bits, typename S&gt; struct hash&lt;wide_integer&lt;Bits, S&gt;&gt;;</pre>
<p>The specialization is enabled (20.14.14). If there is a built-in integral type <code>Integral</code> that has the same typename and width as <code>wide_integer&lt;Bits, S&gt;</code>, and <code>wi</code> is an object of type <code>wide_integer&lt;Bits, S&gt;</code>, then <code>hash&lt;wide_integer&lt;MachineWords, S&gt;&gt;()(wi) == hash&lt;Integral&gt;()(Integral(wi))</code>.</p>


        <h2>V. Feature-testing macro</h2>
        <p>For the purposes of SG10 we recommend the feature-testing macro name <code>__cpp_lib_wide_integer</code>.</p>


        <script type="text/javascript">
            function colorize_texts(texts) {
                for (var i = 0; i < texts.length; ++i) {
                    var text = texts[i].innerHTML;
                    text = text.replace(/namespace|sizeof|long|enum|void|constexpr|extern|noexcept|bool|template|class |struct|auto|const|typename|explicit|public|private|operator|#include|inline| char|typedef|static_assert|static_cast|static/g,"<span class='cppkeyword'>$&<\/span>");
                    text = text.replace(/\/\/[\s\S]+?\n/g,"<span class='cppcomment'>$&<\/span>");
                    //text = text.replace(/\"[\s\S]+?\"/g,"<span class='cpptext'>$&<\/span>");
                    texts[i].innerHTML = text;
                }
            }

            colorize_texts(document.getElementsByTagName("pre"));
            colorize_texts(document.getElementsByTagName("code"));

            function show_hide_deleted() {
                var to_change = document.getElementsByClassName('changed-deleted');
                for (var i = 0; i < to_change.length; ++i) {
                    to_change[i].style.display = (document.getElementById("show_deletions").checked ? 'block' : 'none');
                }
            }
            show_hide_deleted()
        </script>
</body></html>
