<html>
<head>
<title>P0553R2: Bit operations</title>

<style type="text/css">
  ins { text-decoration:none; font-weight:bold; background-color:#A0FFA0 }
  .new { text-decoration:none; font-weight:bold; background-color:#D0FFD0 }
  del { text-decoration:line-through; background-color:#FFA0A0 }  
  strong { font-weight: inherit; color: #2020ff }
  table, td, th { border: 1px solid black; border-collapse:collapse; padding: 5px }
</style>
</head>

<body>
ISO/IEC JTC1 SC22 WG21 P0553R2<br/>
Jens Maurer &lt;Jens.Maurer@gmx.net><br/>
Target audience: LWG<br/>
2017-11-23<br/>

<h1>P0553R2: Bit operations</h1>

<h2>Introduction</h2>

<p>

This paper proposes to add simple free functions for basic bit
operations on all unsigned integer types.

<p>
A previous proposal was in "N3864: A constexpr bitwise operations
library for C++" by Matthew Fioravante.

<p>
The papers P0237Rx propose to introduce bit_value, bit_reference, and
bit_iterator, higher-level concepts for manipulating individual bits
and sequences of bits.  In order to implement efficient standard
algorithms on bit_iterator, it is expected that implementations use
the facilities presented in this paper. By directly exposing the
low-level facilities to programmers, they can use them for their own
purposes, independent of higher-level abstractions in the standard
library.

<p>
It is expected that the functions provided with this proposal will be,
at some later time, overloaded for <code>std::datapar<T></code>, the
nascent SIMD data type (see P0214R2: "Data-Parallel Vector Types &
Operations" by Matthias Kretz).
</p>

<h2>Changes</h2>

P0553R0 was favorably reviewed by SG6 (including the function names)
and forwarded to LEWG. There are only editorial changes in the P0553R1
revision of the paper.
<p>
P0553R1 was favorably reviewed by LEWG with removing the nested inline
namespace and using the header &lt;bit>, and forwarded to LWG at the
Albuquerque, Fall 2017 meeting.


<h2>Design considerations</h2>

These operations can be made available either in
the <code>&lt;bit></code> header proposed by P0237R4, or in a separate
header. LEWG decided to use <code>&lt;bit></code>.
<p>
The bit rotation operations are not limited to rotation counts
less than the bit-width of the integer; it seems most (all?) CPU
instruction sets support longer rotations by simply discarding upper
bits.  Different from bit shifts, this behavior is reasonable because
rotating a 32-bit quantity by 33 bits is indistinguishable from
rotating it by 1 bit.
<p>
The counting operations return "int" quantities, consistent with the
rule "use an int unless you need something else".  This choice does
not reflect, in the type, the fact that counts are always non-negative.
<p>
This proposal uses readable English names for the operations, except
that "left" (towards/affecting the most significant bits) and "right"
(towards/affecting the least significant bits) is abbreviate "l" and "r",
respectively.  The use of "left" and "right" in the operation names is
consistent with the "left" and "right" built-in shift operators.
<p>
An earlier draft of this paper had names such as "countl1",
but lower-case "ell" and the digit "one" are nearly indistinguishable in
some fonts, so now a name like "countl_one" is proposed. This is
slightly baroque, so alternatively "countl(T, bool)" could be used,
with the understanding that the second parameter is often a
compile-time constant, allowing for optimization
opportunities.
<p>
Per prevailing LWG convention, only those functions are marked
<code>noexcept</code> that have a wide constract, i.e. no restrictions
on the values of the function arguments.
<p>
All functions are marked <code>constexpr</code>, assuming that
either compiler intrinsics that work in constant evaluation are
available to the implementation, or the optimizer is good enough to
use the appropriate hardware instructions for operations described
with potentially verbose expressions with built-in operators.
<p>
A tangentially related <code>std::bit_cast</code> is proposed
in P0476R1: "Bit-casting object representations" by JF
Bastien.

<h2>Hardware</h2>

This is an incomplete table showing the extent of hardware support for
the proposed operations.
<p>
<table border="1">

  <tr><th>operation</th> <th>Intel/AMD</th> <th>ARM</th>      <th>PowerPC</th></tr> 
  <tr><td>rotl</td>      <td>ROL</th>       <td>-</td>        <td>rldicl</td></tr>
  <tr><td>rotr</td>      <td>ROR</th>       <td>ROR, EXTR</td><td>-</td></tr>
  <tr><td>popcount</td>  <td>POPCNT</td>    <td>-</td>        <td>popcntb</td></tr>
  <tr><td>countl_zero</td>   <td>BSR, LZCNT</td><td>CLZ</td>      <td>cntlzd</td></tr>
  <tr><td>countl_one</td>   <td>-</td>         <td>CLS</td>      <td>-</td></tr>
  <tr><td>countr_zero</td>   <td>BSF, TZCNT</td><td>-</td>        <td>-</td></tr>
  <tr><td>countr_one</td>   <td>-</td>         <td>-</td>        <td>-</td></tr>

</table>

<h2>Wording</h2>

Add the header <code>&lt;bit></code> to the table in 17.5.1.2 [headers].
<p>

Append a new subsection to clause 20 [utilities] with the following content:

<blockquote class="new">
<h2>23.20 Bit operations [bitops]</h2>

<h3>23.20.1 Header &lt;bit> synopsis [bit.syn]</h3>

<pre>
  namespace std {
  // 23.20.2, rotating   
  template&lt;class T>
    constexpr T rotl(T x, unsigned int s) noexcept;
  template&lt;class T>
    constexpr T rotr(T x, unsigned int s) noexcept;

  // 23.20.3, counting
  template&lt;class T>
    constexpr int countl_zero(T x) noexcept;
  template&lt;class T>
    constexpr int countl_one(T x) noexcept;
  template&lt;class T>
    constexpr int countr_zero(T x) noexcept;
  template&lt;class T>
    constexpr int countr_one(T x) noexcept;
  template&lt;class T>
    constexpr int popcount(T x) noexcept;
  }
  </pre>

In the following descriptions, let N denote
<code>std::numeric_limits&lt;T>::digits</code>.

<h3>23.20.2 Rotating [bitops.rot]</h3>

<pre>
  template&lt;class T>
    constexpr T rotl(T x, unsigned int s) noexcept;
</pre>

<em>Returns:</em> <code>s % N == 0 ? x : (x &lt;&lt; (s % N)) | (x >> (N - (s % N)));</code>
<p>
<em>Remarks:</em> Participates in overload resolution only if T is an
unsigned integer type (3.9.1 [basic.fundamental]).

<pre>
  template&lt;class T>
    constexpr T rotr(T x, unsigned int s) noexcept;
</pre>

<em>Returns:</em> <code>s % N == 0 ? x : (x >> (s % N)) | (x &lt;&lt; (N - (s % N)));</code>
<p>
<em>Remarks:</em> Participates in overload resolution only if T is an
unsigned integer type (3.9.1 [basic.fundamental]).

<h3>23.20.3 Counting [bitops.count]</h3>

<pre>
  template&lt;class T>
    constexpr int countl_zero(T x) noexcept;
</pre>
<em>Returns:</em> The number of consecutive 0 bits, starting from the
most significant bit. [ Note: Returns N if <code>x == 0</code>. ]
<p>
<em>Remarks:</em> Participates in overload resolution only if T is an
unsigned integer type (3.9.1 [basic.fundamental]).

<pre>
  template&lt;class T>
    constexpr int countl_one(T x) noexcept;
</pre>
<em>Returns:</em> The number of consecutive 1 bits, starting from the
most significant bit. [ Note: Returns N if <code>x ==
std::numeric_limits&lt;T>::max()</code>. ]
<p>
<em>Remarks:</em> Participates in overload resolution only if T is an
unsigned integer type (3.9.1 [basic.fundamental]).

<pre>
  template&lt;class T>
    constexpr int countr_zero(T x) noexcept;
</pre>
<em>Returns:</em> The number of consecutive 0 bits, starting from the
least significant bit. [ Note: Returns N if x == 0. ]
<p>
<em>Remarks:</em> Participates in overload resolution only if T is an
unsigned integer type (3.9.1 [basic.fundamental]).

<pre>
  template&lt;class T>
    constexpr int countr_one(T x) noexcept;
</pre>
<em>Returns:</em> The number of consecutive 1 bits, starting from the
least significant bit. [ Note: Returns N if <code>x ==
std::numeric_limits&lt;T>::max()</code>. ]
<p>
<em>Remarks:</em> Participates in overload resolution only if T is an
unsigned integer type (3.9.1 [basic.fundamental]).

<pre>
  template&lt;class T>
    constexpr int popcount(T x) noexcept;
</pre>

<em>Returns:</em> The number of bits set to one in the value of x.
<p>
<em>Remarks:</em> Participates in overload resolution only if T is an
unsigned integer type (3.9.1 [basic.fundamental]).

</blockquote>

<h2>References</h2>
<ul>
  <li>ISO/IEC JTC1 SC22 WG21 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3864.html">N3864</a>: "A constexpr bitwise operations library for C++" by Matthew Fioravante</li>
  <li>ISO/IEC JTC1 SC22 WG21 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0214r2.pdf">P0214R2</a>: "Data-Parallel Vector Types & Operations" by Matthias Kretz</li>
  <li>ISO/IEC JTC1 SC22 WG21 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0237r0.pdf">P0237R0</a>: "On the standardization of fundamental bit manipulation utilities" by Vincent Reverdy and Robert J. Brunner
  <li>ISO/IEC JTC1 SC22 WG21 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0237r4.html">P0237R4</a>: "Wording for fundamental bit manipulation utilities" by Vincent Reverdy and Robert J. Brunner</li>
  <li>ISO/IEC JTC1 SC22 WG21 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0476r1.html">P0476R1</a>: "Bit-casting object representations" by JF Bastien</li>
  <li><a href="http://infocenter.arm.com/help/topic/com.arm.doc.dui0801g/DUI0801
G_armasm_user_guide.pdf">ARM Compiler User Guide</a> [large PDF]</li>
  <li><a href="http://www.intel.com/content/dam/www/public/us/en/documents/manua
ls/64-ia-32-architectures-software-developer-instruction-set-reference-manual-32
5383.pdf">Intel x86 Instruction Set Reference</a> [large PDF]</li>
  <li>PowerPC Architecture Book, Version 2.02: <a href="http://public.dhe.ibm.com/software/dw/library/es-ppcbook1.zip">Book I: PowerPC User Instruction Set Architecture</a> [large PDF inside ZIP]</li>
</ul>

</body>
</html>
