<html>

<head>
  <meta name="description" content="Proposal to rebase the Parallelism TS onto the C++17 Standard">
  <meta name="keywords" content="C++,C++17,cplusplus,parallelism,TS,wg21,SG1">
  <meta name="author" content="Alisdair Meredith">

  <title>Rebase the Parallelism TS onto the C++17 Standard</title>

  <style type="text/css">
    ins {background-color:#A0FFA0}
    del {background-color:#FFA0A0}
    p {text-align:justify}
    li {text-align:justify}
    blockquote.note
    {
      background-color:#E0E0E0;
      padding-left: 15px;
      padding-right: 15px;
      padding-top: 1px;
      padding-bottom: 1px;
    }
  </style>
</head>

<body>
<table>
<tr>
  <td align="left">Doc. no.</td>
  <td align="left">P0776R0</td>
</tr>
<tr>
  <td align="left">Date:</td>
  <td align="left">2017-09-08</td>
</tr>
<tr>
  <td align="left">Project:</td>
  <td align="left">Programming Language C++</td>
</tr>
<tr>
  <td align="left">Audience:</td>
  <td align="left">SG1, LEWG</td>
</tr>
<tr>
  <td align="left">Reply to:</td>
  <td align="left">Alisdair Meredith &lt;<a href="mailto:ameredith1@bloomberg.net">ameredith1@bloomberg.net</a>&gt;</td>
</tr>
</table>

<h1>Rebase the Parallelism TS onto the C++17 Standard</h1>

<h2>Table of Contents</h2>
<ol>
<li><a href="#rev.hist">Revision History</a></li>
  <ul>
  <li><a href="#rev.0">Revision 0</a></li>
  </ul>
<li><a href="#1.0">1 Introduction</a></li>
<li><a href="#2.0">2 Stating the problem</a></li>
  <ul>
  <li><a href="#2.1">Consistency of propagation traits</a></li>
  </ul>
<li><a href="#3.0">3 Propose Solution</a></li>
<li><a href="#4.0">4 Other Directions</a></li>
<li><a href="#5.0">5 Formal Wording</a></li>
<li><a href="#6.0">6 Acknowledgements</a></li>
<li><a href="#7.0">7 References</a></li>
</ol>


<h2><a name="rev.hist">Revision History</a></h2>

<h3><a name="rev.0">Revision 0</a></h3>
<p>
Original version of the paper for the 2017 pre-Albuquerque mailing.
</p>


<h2><a name="1.0">1 Introduction</a></h2>
<p>
The current working draft for the Parallelism TS is based on C++14.  Many of
the features were significantly revised and adopted into the C++17 standard,
so this paper proposed revising the draft to reflect the new standard.
</p>


<h2><a name="2.0">2 Stating the problem</a></h2>
<p>
The first Parallelism TS achieved its purpose, and its contents were adopted
into C++17 by applying the paper
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0024r2">P0024R2</a>
out of the Jacksonville 2016 meeting.  However, there were several issues with
the original TS that were resolved in the C++17 process, incorporating a further
11 papers and 4 LWG issue resolutions that were not applied back to the TS.
Future TSes should be based on that more recent specification.
</p>

<h2><a name="2.1">2.1 The Wrong Namespace Formulation is Used</a></h2>
<p>
There are two namespace conventions for use inside the <tt>experimental</tt>
namespace intended for TSes.  The simplest is to use an inline namespace nested
directly inside namespace <tt>std::experimental</tt> named after the TS, and
incorporating a version suffix.  This is used when the intent is to land the
TS features directly into namespace <tt>std</tt>, should they be incorporated
into a future standard.  The alternative is to have a named (non-inline)
namespace nested inside namespace <tt>std::experimental</tt>, and an inline
version-number namespace inside that.  This form is intended for use when it is
expected that the named namespace will wrap the TS facilities in namespace
<tt>std</tt> in the event that they are incorporated into a future standard.
</p>

<p>
The parallelism TS uses the second formulation, while document the intended
adoption plan corresponds to the first formulation, and this is how it was
applied by
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0024r2">P0024R2</a>.
</p>

<h2><a name="2.2">2.2 <tt>exception_list</tt> is Underspecified</a></h2>
<p>
There were a number of issues with the <tt>exception_list</tt> facility proposed
by the original TS.  One major concern was that there was no way for a user to
populate an <tt>exception_list</tt> of their own, if they wanted to provide their
own parallel algorithms following the standard interface.  The intent was always
to nail this down as part of adopting the specification into the standard, but
doing so turned out to be more controversial than expected, and ultimately this
form of error handling was deferred to a future set of parallel execution
policies.
</p>

<p>
The most prominent concerns are discussed in paper
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0322r0">P0322R0</a>
but there is still no clear sign of progress on using this error-reporting
scheme, or even if the <tt>exception_list</tt> class should be immutable.  There
are important design issues to reconsider for its use in the new <tt>task_block</tt>
facility, given that the class is no longer needed for the parallel algorithms.
It may be possible to resolve the problematic design concerns if the context is
a class intended only for use in the <tt>task_block</tt> interface.
</p>


<h2><a name="2.3">2.3 Exception-handling Strategy Changed Completely</a></h2>
<p>
The parallel algorithms in C++17 use a different error reporting strategy, which
is deferred to the parallel execution policy (and by default, simply calls
<tt>terminate</tt>).  It would seem unhelpful to retain the rejected error
reporting behavior in the TS.  If it were to be retained, it would be specified
differently, by adopting new execution policies that have that behavior, which
would have no impact on the specification of the algorithms themselves, so the
duplication within the TS would be redundant.
</p>


<h2><a name="2.4">2.4 Dynamic Execution Policy was not Adopted</a></h2>
<p>
There were concerns about adopting execution policies with runtime state (among
other concerns) so the dynamic execution policy was deliberately dropped from
the feature set adopted for C++17.  Given the implementation concerns, and a
deliberate poll to remove the feature as part of standardization, its ongoing
presence in the TS is questionable. 
</p>

<h2><a name="2.5">2.5 Policy Types and Values Have New Names</a></h2>
<p>
The names for the remaining three policies went through several revisions, and
do not match the policy names in the TS.  Given the policies for the intended
semantics have been adopted, we should not have duplicate policies with
different names in the TS.
</p>

<h2><a name="2.6">2.6 Many Algorithms Changed Specification</a></h2>
<p>
A variety of concerns came up with the specification for the algorithms,
questioning the assumption that the serial specification was adequate for the
parallel form of each algorithm.  Several algorithms required explicit wording
to get the complexity correct.  One or two algorithms lost their parallel form,
as it was unhelpful (due to mandatory serial stages) in the presence of the
more general parallel algorithms added by the TS.  Similarly, it was not clear
what the correct restrictions to impose on algorithms taking input and output
iterators would be in order to support parallelization (through some kind of
scatter/gather) approach, and requiring support in all cases essentially
serialized those algorithms, even where better approaches may be known to work.
Hence, the iterator categories for many algorithms were changed, which required
separate declarations for each algorithm, rather than the table with a list of
names specified in this TS.  Porting the revised specification for each algorithm
into the TS is of dubious benefit, when we could just defer to the standard
directly,
</p>

<h2><a name="2.7">2.7 Forward Progress Guarantees</a></h2>
<p>
Two papers, 
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0296r2">P0296R2</a>
and 
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0299r1">P0299R1</a>,
provide the vocabulary essential to provide forward progress guarantees, and
then apply that vocabulary to the standard library.  This wording is found only
in C++17, and not back-ported to the TS, so we need to at least incorporate the
C++17 specification by reference.
</p>


<h3><a name="3.0">3 Propose Solution</a></h3>
<p>
The resolution proposed by this paper is to update the reference to the base
C++ Standard to refer to ISO 14882:2017, rather than 2014, and then strike the
text for all components that were adopted (in some form) into C++17.
</p>

<p>
Essentially two components remain, <tt>exception_list</tt> remains underspecified,
with no progress on understanding the needs or implementation details.  However,
the new <tt>task_block</tt> component is specified to report errors using this
class, so it must remain, unless <tt>task_block</tt> is respecified to
use an error handling strategy more compatible with C++17.
</p>

<p>
This paper further recommends opening library issues to address the concerns
raised by the ongoing presence of <tt>exception_list</tt> in this TS.
</p>

<p>
Finally, this paper proposes using the inline namespace <tt>parallelism_v2</tt>
to contain the contents of this experimental TS, rather than an inline version
namespace inside a nested <tt>parallel</tt> namespace, that is not intended for
integration with a future C++ standard.
</p>


<h3><a name="4.0">4 Other Directions</a></h3>
<p>
Another option would be to apply all of the C++17 papers to the TS.  However,
that would not be as simple as applying the edits to the standard, as many of
those papers adjust words that are not present in the TS.  It is also not
entirely clear that there is a benefit in duplicating the whole specification
in this way.
</p>

<p>
Another idea is that some of the changes for C++17 were the 'minimal' changes
necessary to get a well-supported specification at this time, with the
expectation that a number of issues would be revisited in time, with more
generic (or specific) specification to follow, allowing more parallelism with
better error-handling strategies.  It may be worth retaining the original TS
specification as a place to perform those ongoing experiments.  This direction
is rejected by this paper as holding over far too much of a pre-standard
specification with a broad set of defects unrelated to that task.  It would be
preferred to add targeted new features as those proposals arise.
</p>

<p>
One last option is to entirely strike the specification for <tt>exception_list</tt>
given the issues that arose trying to nail down a complete specification.  However,
it remains an essential part of the error-handling strategy for <tt>task_block</tt>,
and this paper does not aim to review existing components that are not directly
impacted by the adoption of C++17.  While a review of this design in the light
of C++17 is encouraged, this paper is not the place for that review.
</p>


<h3><a name="5.0">5 Formal Wording</a></h3>
<p>
Strike the sections <del>deleted</del> in the table of contents below, entirely
from the working paper:
</p>
<blockquote>
<ol>
<li>Scope</li>
<li>Normative references</li>
<li><del>Terms and definitions</del></li>
<li>General</li>
  <ol>
  <li>Namespaces and headers</li>
  <li>Feature-testing recommendations</li>
  </ol>
<li><del>Execution policies</del></li>
  <ol>
  <li><del>In general</del></li>
  <li><del>Header <tt>&lt;experimental/execution_policy&gt;</tt> synopsis</del></li>
  <li><del>Execution policy type trait</del></li>
  <li><del>Sequential execution policy</del></li>
  <li><del>Parallel execution policy</del></li>
  <li><del>Parallel+Vector execution policy</del></li>
  <li><del>Dynamic execution policy</del></li>
    <ol>
    <li><del><tt>execution_policy</tt> construct/assign</del></li>
    <li><del><tt>execution_policy</tt> object access</del></li>
    </ol>
  <li><del>Execution policy objects</del></li>
  </ol>
<li>Parallel exceptions</li>
  <ol>
  <li><del>Exception reporting behavior</del></li>
  <li>Header <tt>&lt;experimental/exception_list&gt;</tt> synopsis</li>
  </ol>
<li><del>Parallel algorithms</del></li>
  <ol>
  <li><del>In general</del></li>
    <ol>
    <li><del>Requirements on user-provided function objects</del></li>
    <li><del>Effect of execution policies on algorithm execution</del></li>
    <li><del>ExecutionPolicy algorithm overloads</del></li>
    </ol>
  <li><del>Definitions</del></li>
  <li><del>Non-Numeric Parallel Algorithms</del></li>
    <ol>
    <li><del>Header <tt>&lt;experimental/algorithm&gt;</tt> synopsis</del></li>
    <li><del>For each</del></li>
    </ol>
  <li><del>Numeric Parallel Algorithms</li>
    <ol>
    <li><del>Header <tt>&lt;experimental/numeric&gt;</tt> synopsis</del></li>
    <li><del>Reduce</del></li>
    <li><del>Exclusive scan</del></li>
    <li><del>Inclusive scan</del></li>
    <li><del>Transform reduce</del></li>
    <li><del>Transform exclusive scan</del></li>
    <li><del>Transform inclusive scan</del></li>
    </ol>
  </ol>
<li>Task Block</li>
  <ol>
  <li>Header <tt>&lt;experimental/task_block&gt;</tt> synopsis</li>
  <li>Class <tt>task_cancelled_exception</tt></li>
    <ol>
    <li><tt>task_cancelled_exception</tt> member function <tt>what</tt></li>
    </ol>
  <li>Class <tt>task_block</tt></li>
    <ol>
    <li><tt>task_block</tt> member function template <tt>run</tt></li>
    <li><tt>task_block</tt> member function <tt>wait</tt></li>
    </ol>
  <li>Function template <tt>define_task_block</tt></li>
  <li>Exception Handling</li>
  </ol>
</ol>
</blockquote>

<p>
In addition, make the following edits to the clauses that remain.  Original
clause numbering is retained for clarity, although it is expected that the
clauses will be renumbered applying the edits above.
</p>

<blockquote>

<h4>2 Normative references [parallel.references]</h4>
<ol>
<li>
The following referenced document is indispensable for the application of this
document. For dated references, only the edition cited applies. For undated
references, the latest edition of the referenced document (including any
amendments) applies.
<ul><li>
ISO/IEC 14882:<ins>2017</ins><del>&mdash;1</del>, Programming Languages &mdash; C++
</li></ul>

</li>

<li>
ISO/IEC 14882:<ins>2017</ins><del>&mdash;</del> is herein called the C++ Standard.
The library described in ISO/IEC 14882:<ins>2017</ins><del>&mdash;</del> clauses
<del>17-30</del><ins>20-33</ins> is herein called the C++ Standard Library. The
C++ Standard Library components described in ISO/IEC
14882:<ins>2017</ins><del>&mdash;</del> clauses <del>25, 26.7 and 20.7.2</del>
<ins>28, 29.8 and 23.10.10</ins> are herein called the C++ Standard Algorithms
Library.
</li>

<li>
Unless otherwise specified, the whole of the C++ Standard's Library introduction
<del>(C++14 §17)</del><ins>(C++17 §20)</del> is included into this Technical
Specification by reference.
</li>
</ol>
<p><del>1) To be published. Section references are relative to N3937.</del></p>


<h4>4.1 Namespaces and headers [parallel.general.namespaces]</h4>
<ol>
<li>
Since the extensions described in this Technical Specification are experimental
and not part of the C++ Standard Library, they should not be declared directly
within namespace std. Unless otherwise specified, all components described in
this Technical Specification are declared in namespace
<tt>std::experimental::<del>parallel::v2</del><ins>parallelism_v2</ins></tt>.
<pre></pre>
[ <i>Note:</i> Once standardized, the components described by this Technical
Specification are expected to be promoted to namespace <tt>std</tt>. &mdash; <i>end note</i> ]
</li>

<li>
Unless otherwise specified, references to such entities described in this
Technical Specification are assumed to be qualified with
<tt>std::experimental::<del>parallel::v2</del><ins>parallelism_v2</ins></tt>,
and references to entities described in the C++ Standard Library are assumed to
be qualified with <tt>std::</tt>.
</li>

<li>
Extensions that are expected to eventually be added to an existing header
<tt>&lt;meow&gt;</tt> are provided inside the <tt>&lt;experimental/meow&gt;</tt>
header, which shall include the standard contents of <tt>&lt;meow&gt;</tt> as if by
<blockquote><pre>
    #include &lt;meow&gt;
</pre></blockquote>
</li>
</ol>


<h4>4.2 Feature-testing recommendations [parallel.general.features]</h4>
<ol>
<li>
An implementation that provides support for this Technical Specification shall
define the feature test macro(s) in Table 1.
</li>
</ol>

Table 1 &mdash; Feature Test Macro(s)
<table>
<tr>
  <td><b>Name</b></td>
  <td><b>Value</b></td>
  <td><b>Header</b></td>
</tr>
<tr>
  <td><del><tt>__cpp_lib_experimental_parallel_algorithm</tt></del></td>
  <td><del>201505</del></td>
  <td><del><tt>&lt;experimental/algorithm&gt;</tt></del></td>
</tr>
<tr>
  <td> </td>
  <td> </td>
  <td><del><tt>&lt;experimental/exception_list&gt;</tt></del></td>
</tr>
  <td> </td>
  <td> </td>
  <td><del><tt>&lt;experimental/execution_policy&gt;</tt></del></td>
</tr>
  <td> </td>
  <td> </td>
  <td><del><tt>&lt;experimental/numeric&gt;</tt></del></td>
</tr>

<tr>
  <td><tt>__cpp_lib_experimental_parallel_task_block</tt></td>
  <td>201510</td>
  <td><ins><tt>&lt;experimental/exception_list&gt;</tt><ins></td>
</tr>
  <td> </td>
  <td> </td>
  <td><tt>&lt;experimental/task_block&gt;</tt></td>
</tr>
</table>

<h4>6.2 Header <tt>&lt;experimental/exception_list&gt;</tt> synopsis [parallel.exceptions.synopsis]</h4>
<blockquote><pre>
<del>namespace std {</del>
namespace <ins>std::</ins>experimental {
namespace <ins>inline</ins> parallel<ins>ism_v2</ins> {
<del>inline namespace v2 {</del>

  class exception_list : public exception
  {
    public:
      <del>typedef <i>unspecified</i> iterator;</del>
      <ins>using iterator = <i>unspecified</i>;</ins>
  
      size_t size() const noexcept;
      iterator begin() const noexcept;
      iterator end() const noexcept;

      const char* what() const noexcept override;
  };
<del>}</del>
}
}
<del>}</del>
</pre></blockquote>

<ol>
<li>
The class <tt>exception_list</tt> owns a sequence of <tt>exception_ptr</tt> objects.
<del>The parallel algorithms may use the <tt>exception_list</tt> to communicate
uncaught exceptions encountered during parallel execution to the caller of the
algorithm.</del>
</li>
</ol>


<h4>8.1 Header <tt>&lt;experimental/task_block&gt;</tt> synopsis [parallel.task_block.synopsis]</h4>
<blockquote><pre>
<del>namespace std {</del>
namespace <ins>std::</ins>experimental {
namespace <ins>inline</ins> parallel<ins>ism_v2</ins> {
<del>inline namespace v2 {</del>
  class task_cancelled_exception;

  class task_block;

  template&lt;class F&gt;
    void define_task_block(F&amp;&amp; f);

  template&lt;class F&gt;
    void define_task_block_restore_thread(F&amp;&amp; f);
<del>}</del>
}
}
<del>}</del>
</pre></blockquote>
     
<h4>8.2 Class <tt>task_cancelled_exception</tt> [parallel.task_block.task_cancelled_exception]</h4>
<blockquote><pre>
<del>namespace std {</del>
namespace <ins>std::</ins>experimental {
namespace <ins>inline</ins> parallel<ins>ism_v2</ins> {
<del>inline namespace v2 {</del>

  class task_cancelled_exception : public exception
  {
    public:
      task_cancelled_exception() noexcept;
      virtual const char* what() const noexcept;
  };
<del>}</del>
}
}
<del>}</del>
</pre></blockquote>

<h4>8.3 Class <tt>task_block</tt> [parallel.task_block.class]</h4>
<blockquote><pre>
<del>namespace std {</del>
namespace <ins>std::</ins>experimental {
namespace <ins>inline</ins> parallel<ins>ism_v2</ins> {
<del>inline namespace v2 {</del>

  class task_block
  {
    private:
      ~task_block();

    public:
      task_block(const task_block&amp;) = delete;
      task_block&amp; operator=(const task_block&amp;) = delete;
      void operator&amp;() const = delete;

      template&lt;class F&gt;
        void run(F&amp;&amp; f);

      void wait();
  };
<del>}</del>
}
}
<del>}</del>
</pre></blockquote>

</blockquote>



<h2><a name="6.0">6 Acknowledements</h2>
<p>
Thanks to Jared Hoberock for the initial review of this paper.
</p>


<h2><a name="7.0">7 References</h2>
<p>
The following papers and issues were applied to the C++ Working Paper as part
of C++17:
</p>
<ul>
  <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0024r2">P0024R2</a> The Parallelism TS Should be Standardized, Jared Hoberock</li>
  <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0296r2">P0296R2</a> Forward progress guarantees: Base definitions, Torvald Riegel</li>
  <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0299r1">P0299R1</a> Forward progress guarantees for the Parallelism TS features, Torvald Riegel</li>
  <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0336r1">P0336R1</a> Better Names for Parallel Execution Policies in C++17, Pablo Halpern</li>
  <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0394r4">P0394R4</a> Hotel Parallelifornia: terminate() for Parallel Algorithms Exception Handling, JF Bastien, Bryce Adelstein Lelbach</li>
  <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0452r1">P0452R1</a> Unifying <tt>&lt;numeric&gt;</tt> Parallel Algorithms, Bryce Adelstein Lelbach</li>
  <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0467r2">P0467R2</a> Iterator Concerns for Parallel Algorithms, Alisdair Meredith</li>
  <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0502r0">P0502R0</a> Throwing out of a parallel algorithm terminates&mdash;but how?, JF Bastien, Bryce Adelstein Lelbach, H. Carter Edwards</li>
  <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0518r1">P0518R1</a> Allowing copies as arguments to function objects given to parallel algorithms, David S. Hollman, Jonathan Lifflander, Michael Wong, Detlef Vollmann</li>
  <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0523r1">P0523R1</a> Wording for CH 10: Complexity of parallel algorithms, Detlef Vollmann</li>
  <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0574r1">P0574R1</a> Algorithm Complexity Constraints and Parallel Overloads, Anthony Williams, Bryce Adelstein Lelbach</li>
  <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0623r0">P0623R0</a> Final C++17 Parallel Algorithms Fixes, Bryce Adelstein Lelbach, Alisdair Meredith, Anthony Williams</li>
  <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2689">LWG 2687</a> <tt>{inclusive,exclusive}_scan</tt> misspecified</li>
  <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2689">LWG 2689</a> Parallel versions of <tt>std::copy</tt> and <tt>std::move</tt> shouldn't be in order</li>
  <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2718">LWG 2718</a> Parallelism bug in [algorithms.parallel.exec]p2</li>
  <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2727">LWG 2727</a> Parallel algorithms with <tt>constexpr</tt> specifier</li>
</ul>

<p>
The following papers informed the discussion of the papers and issues above:
</p>
<ul>
  <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0322r0">P0322R0</a> <tt>exception_list</tt>, Bryce Adelstein Lelbach, Alisdair Meredith, Jared Hoberock</li>
  <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0333r0">P0333R0</a> Improving Parallel Algorithm Exception Handling, Bryce Adelstein Lelbach</li>
  <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0451r0">P0451R0</a> Future-Proofing Parallel Algorithms Exception Handling, Bryce Adelstein Lelbach, Alisdair Meredith</li>
  <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0571r0">P0571R0</a> Type Requirements for <tt>&lt;numeric&gt;</tt> Algorithms, Bryce Adelstein Lelbach</li>


</body>
</html>
