<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>
<head>
  <meta name="generator" content=
  "HTML Tidy for OS/2 (vers 1 September 2005), see www.w3.org">
<style type="text/css">
      del { font-weight:bold;background-color:#ffa0a0 }
      ins { font-weight:bold;background-color:#a0ffa0 }
      blockquote {
      display: block;
      font-family: "Times New Roman";
      background-color:lightgray;
      margin-top: 1em;
      margin-bottom: 1em;
      margin-left: 40px;
      margin-right: 40px
      }
</style>

  <title>N2xxx: intmax_t and math functions</title>
</head>

<body>
  <p><br>
  <!-- Who are the authors... -->
   <b>Submitter:</b>Fred J. Tydeman<br>
  <!-- What is the date of submission. yyyy-mm-dd -->
   <b>Submission Date:</b> 2020-mm-dd<br>
  <b>Document:</b> WG14 N2xxx<br>
  <b>Title:</b> N2xxx: intmax_t and math functions<br>
  <b>Reference Documents:</b> N2478, N2525</p>

  <p>Summary</p>Due to issues raised by the WG14 committee with
  [u]intmax_t, several of the CFP related functions ([u]fromfp[x],
  compoundn, pown, rootn) should be changed to not use [u]intmax_t.

  <p>The WG14 consideration of removing [u]intmax_t, sparked the
  CFP discussion. We concluded that changing the interfaces to not
  use [u]intmax_t would be better anyway (even if [u]intmax_t were
  not removed). Introducing type [u]intmax_t into an expression via
  a function return type could have unpredictable negative
  performance implications.</p>

  <p>In general, replace [u]intmax_t with the floating type used as
  the parameter.</p>

  <p>Change</p>

  <blockquote>
    7.12.9.10 The fromfp and ufromfp functions
  </blockquote>

  <blockquote>
    Synopsis
  </blockquote>

  <blockquote>
    <pre>
<code>
1 #include <stdint.h>
  #include <math.h>
  intmax_t fromfp(double x, int round, unsigned int width);
  intmax_t fromfpf(float x, int round, unsigned int width);
  intmax_t fromfpl(long double x, int round, unsigned int width);
  uintmax_t ufromfp(double x, int round, unsigned int width);
  uintmax_t ufromfpf(float x, int round, unsigned int width);
  uintmax_t ufromfpl(long double x, int round, unsigned int width);
  #ifdef __STDC_IEC_60559_DFP__
  intmax_t fromfpd32(_Decimal32 x, int round, unsigned int width);
  intmax_t fromfpd64(_Decimal64 x, int round, unsigned int width);
  intmax_t fromfpd128(_Decimal128 x, int round, unsigned int width);
  uintmax_t ufromfpd32(_Decimal32 x, int round, unsigned int width);
  uintmax_t ufromfpd64(_Decimal64 x, int round, unsigned int width);
  uintmax_t ufromfpd128(_Decimal128 x, int round, unsigned int width);
  #endif
</code>
    
</pre>
  </blockquote>

  <blockquote>
    Description
  </blockquote>

  <blockquote>
    <p>2 The <b>fromfp</b> and <b>ufromfp</b> functions round x,
    using the math rounding direction indicated by <b>round</b>, to
    a signed or unsigned integer, respectively, of <b>width</b>
    bits, and return the result value in the integer type
    designated by <b>intmax_t</b> or <b>uintmax_t</b>,
    respectively. If the value of the <b>round</b> argument is not
    equal to the value of a math rounding direction macro, the
    direction of rounding is unspecified. If the value of
    <b>width</b> exceeds the width of the function type, the
    rounding is to the full width of the function type. The
    <b>fromfp</b> and <b>ufromfp</b> functions do not raise the
    "inexact" floating-point exception. If x is infinite or NaN or
    rounds to an integral value that is outside the range of any
    supported integer type of the specified width, or if width is
    zero, the functions return an unspecified value and a domain
    error occurs.</p>
  </blockquote>

  <p>to</p>

  <blockquote>
    7.12.9.10 The fromfp and ufromfp functions
  </blockquote>

  <blockquote>
    Synopsis
  </blockquote>

  <blockquote>
    <pre>
<code>
1 #include <stdint.h>
  #include <math.h>
  <del>intmax_t</del> <ins>double</ins> fromfp(double x, int round, unsigned int width);
  <del>intmax_t</del> <ins>float</ins> fromfpf(float x, int round, unsigned int width);
  <del>intmax_t</del> <ins>long double</ins> fromfpl(long double x, int round, unsigned int width);
  <del>uintmax_t</del> <ins>double</ins> ufromfp(double x, int round, unsigned int width);
  <del>uintmax_t</del> <ins>float</ins> ufromfpf(float x, int round, unsigned int width);
  <del>uintmax_t</del> <ins>long double</ins> ufromfpl(long double x, int round, unsigned int width);
  #ifdef __STDC_IEC_60559_DFP__
  <del>intmax_t</del> <ins>_Decimal32</ins> fromfpd32(_Decimal32 x, int round, unsigned int width);
  <del>intmax_t</del> <ins>_Decimal64</ins> fromfpd64(_Decimal64 x, int round, unsigned int width);
  <del>intmax_t</del> <ins>_Decimal128</ins> fromfpd128(_Decimal128 x, int round, unsigned int width);
  <del>uintmax_t</del> <ins>_Decimal32</ins> ufromfpd32(_Decimal32 x, int round, unsigned int width);
  <del>uintmax_t</del> <ins>_Decimal64</ins> ufromfpd64(_Decimal64 x, int round, unsigned int width);
  <del>uintmax_t</del> <ins>_Decimal128</ins> ufromfpd128(_Decimal128 x, int round, unsigned int width);
  #endif
</code>
    
</pre>
  </blockquote>

  <blockquote>
    Description
  </blockquote>

  <blockquote>
    <p>2 The <b>fromfp</b> and <b>ufromfp</b> functions round x,
    using the math rounding direction indicated by <b>round</b>, to
    a signed or unsigned integer, respectively. <del>, of
    <b>width</b> bits, and return the result value in the integer
    type designated by <b>intmax_t</b> or <b>uintmax_t</b>,
    respectively.</del> <ins>If <b>width</b> is nonzero and the
    resulting integer is within the range</ins></p>
    <pre>
<ins>   [-2**(width-1), 2**(width-1) - 1], for signed
   [0, 2**width - 1], for unsigned
</ins>
</pre>

    <p><ins>the functions return the integer value (represented in
    floating type). Otherwise, if <b>width</b> is zero or <b>x</b>
    does not round to an integer within the range, the functions
    return a NaN (of the type of the <b>x</b> argument, if
    available), else the value of <b>x</b>, and a domain error
    occurs.</ins> If the value of the <b>round</b> argument is not
    equal to the value of a math rounding direction macro
    <ins>(7.12)</ins>, the direction of rounding is unspecified.
    <del>If the value of <b>width</b> exceeds the width of the
    function type, the rounding is to the full width of the
    function type.</del> The <b>fromfp</b> and <b>ufromfp</b>
    functions do not raise the "inexact" floating-point exception.
    <del>If x is infinite or NaN or rounds to an integral value
    that is outside the range of any supported integer type of the
    specified width, or if width is zero, the functions return an
    unspecified value and a domain error occurs.</del></p>
  </blockquote>

  <p>And insert another example after the existing example:</p>

  <blockquote>
    <p><ins>5 EXAMPLE Unsigned integer wrapping is not performed
    in</ins></p>
    <pre>
<code>
<ins>ufromfp(-3.0, FP_INT_UPWARD, UINT_WIDTH) /* domain error */</ins>
</code>
    
</pre>
  </blockquote>

  <p>Also, in F.10.6.10:</p>

  <p>Change:</p>

  <blockquote>
    <p>1 The fromfp and ufromfp functions raise the "invalid"
    floating-point exception and return an unspecified value if the
    floating-point argument x is infinite or NaN or rounds to an
    integral value that is outside the range of any supported
    integer type of the specified width.</p>
  </blockquote>

  <p>to:</p>

  <blockquote>
    <p>1 The fromfp and ufromfp functions raise the "invalid"
    floating-point exception and return <del>an unspecified
    value</del> <ins>a NaN</ins> if the <ins>argument <b>width</b>
    is zero or if the</ins> floating-point argument x is infinite
    or NaN or rounds to an integer value that is outside the range
    <del>of any supported integer type of the specified width</del>
    <ins>determined by the argument width (see
    7.12.9.10)</ins>.</p>
  </blockquote>

  <p>Change</p>

  <blockquote>
    7.12.9.11 The fromfpx and ufromfpx functions
  </blockquote>

  <blockquote>
    Synopsis
  </blockquote>

  <blockquote>
    <pre>
<code>
1 #include <stdint.h>
  #include <math.h>
  intmax_t fromfpx(double x, int round, unsigned int width);
  intmax_t fromfpfx(float x, int round, unsigned int width);
  intmax_t fromfplx(long double x, int round, unsigned int width);
  uintmax_t ufromfpx(double x, int round, unsigned int width);
  uintmax_t ufromfpfx(float x, int round, unsigned int width);
  uintmax_t ufromfplx(long double x, int round, unsigned int width);
  #ifdef __STDC_IEC_60559_DFP__
  intmax_t fromfpd32x(_Decimal32 x, int round, unsigned int width);
  intmax_t fromfpd64x(_Decimal64 x, int round, unsigned int width);
  intmax_t fromfpd128x(_Decimal128 x, int round, unsigned int width);
  uintmax_t ufromfpd32x(_Decimal32 x, int round, unsigned int width);
  uintmax_t ufromfpd64x(_Decimal64 x, int round, unsigned int width);
  uintmax_t ufromfpd128x(_Decimal128 x, int round, unsigned int width);
  #endif
</code>
    
</pre>
  </blockquote>

  <blockquote>
    Description
  </blockquote>

  <p>to</p>

  <blockquote>
    7.12.9.11 The fromfpx and ufromfpx functions
  </blockquote>

  <blockquote>
    Synopsis
  </blockquote>

  <blockquote>
    <pre>
<code>
1 #include <stdint.h>
  #include <math.h>
  <del>intmax_t</del> <ins>double</ins> fromfpx(double x, int round, unsigned int width);
  <del>intmax_t</del> <ins>float</ins> fromfpfx(float x, int round, unsigned int width);
  <del>intmax_t</del> <ins>long double</ins> fromfplx(long double x, int round, unsigned int width);
  <del>uintmax_t</del> <ins>double</ins> ufromfpx(double x, int round, unsigned int width);
  <del>uintmax_t</del> <ins>float</ins> ufromfpfx(float x, int round, unsigned int width);
  <del>uintmax_t</del> <ins>long double</ins> ufromfplx(long double x, int round, unsigned int width);
  #ifdef __STDC_IEC_60559_DFP__
  <del>intmax_t</del> <ins>_Decimal32</ins> fromfpd32x(_Decimal32 x, int round, unsigned int width);
  <del>intmax_t</del> <ins>_Decimal64</ins> fromfpd64x(_Decimal64 x, int round, unsigned int width);
  <del>intmax_t</del> <ins>_Decimal128</ins> fromfpd128x(_Decimal128 x, int round, unsigned int width);
  <del>uintmax_t</del> <ins>_Decimal32</ins> ufromfpd32x(_Decimal32 x, int round, unsigned int width);
  <del>uintmax_t</del> <ins>_Decimal64</ins> ufromfpd64x(_Decimal64 x, int round, unsigned int width);
  <del>uintmax_t</del> <ins>_Decimal128</ins> ufromfpd128x(_Decimal128 x, int round, unsigned int width);
  #endif
</code>
    
</pre>
  </blockquote>

  <blockquote>
    Description
  </blockquote>

  <p>Also, in F.10.6.11:</p>

  <p>Change:</p>

  <blockquote>
    The fromfpx and ufromfpx functions raise the "invalid"
    floating-point exception and return an unspecified value if the
    floating-point argument x is infinite or NaN or rounds to an
    integral value that is outside the range of any supported
    integer type of the specified width.
  </blockquote>

  <p>to:</p>

  <blockquote>
    The fromfpx and ufromfpx functions raise the "invalid"
    floating-point exception and return <del>an unspecified
    value</del><ins>a NaN</ins> if the floating-point argument x is
    infinite or NaN or rounds to an integral value that is outside
    the range <del>of any supported integer type of the specified
    width</del><ins>determined by the argument width (see
    7.12.9.11)</ins>.
  </blockquote>

  <p>The three function families compoundn, rootn, pown have the
  simple change of replacing <b>intmax_t</b> with <b>long long
  int</b>.</p>

  <p>Change</p>

  <blockquote>
    <pre>
<code>
7.12.7.2 The compoundn functions
Synopsis
1 #include <stdint.h>
  #include <math.h>
  double compoundn(double x, intmax_t n);
  float compoundnf(float x, intmax_t n);
  long double compoundnl(long double x, intmax_t n);
  #ifdef __STDC_IEC_60559_DFP__
  _Decimal32 compoundnd32(_Decimal32 x, intmax_t n);
  _Decimal64 compoundnd64(_Decimal64 x, intmax_t n);
  _Decimal128 compoundnd128(_Decimal128 x, intmax_t n);
  #endif
</code>
</pre>
  </blockquote>

  <p>to</p>

  <blockquote>
    <pre>
<code>
7.12.7.2 The compoundn functions
Synopsis
1 #include <stdint.h>
  #include <math.h>
  double compoundn(double x, <del>intmax_t</del><ins>long long int</ins> n);
  float compoundnf(float x, <del>intmax_t</del><ins>long long int</ins> n);
  long double compoundnl(long double x, <del>intmax_t</del><ins>long long int</ins> n);
  #ifdef __STDC_IEC_60559_DFP__
  _Decimal32 compoundnd32(_Decimal32 x, <del>intmax_t</del><ins>long long int</ins> n);
  _Decimal64 compoundnd64(_Decimal64 x, <del>intmax_t</del><ins>long long int</ins> n);
  _Decimal128 compoundnd128(_Decimal128 x, <del>intmax_t</del><ins>long long int</ins> n);
  #endif
</code>
</pre>
  </blockquote>

  <p>Change</p>

  <blockquote>
    <pre>
<code>
7.12.7.6 The pown functions
Synopsis
1 #include <stdint.h>
  #include <math.h>
  double pown(double x, intmax_t n);
  float pownf(float x, intmax_t n);
  long double pownl(long double x, intmax_t n);
  #ifdef __STDC_IEC_60559_DFP__
  _Decimal32 pownd32(_Decimal32 x, intmax_t n);
  _Decimal64 pownd64(_Decimal64 x, intmax_t n);
  _Decimal128 pownd128(_Decimal128 x, intmax_t n);
  #endif
</code>
</pre>
  </blockquote>

  <p>to</p>

  <blockquote>
    <pre>
<code>
7.12.7.6 The pown functions
Synopsis
1 #include <stdint.h>
  #include <math.h>
  double pown(double x, <del>intmax_t</del><ins>long long int</ins> n);
  float pownf(float x, <del>intmax_t</del><ins>long long int</ins> n);
  long double pownl(long double x, <del>intmax_t</del><ins>long long int</ins> n);
  #ifdef __STDC_IEC_60559_DFP__
  _Decimal32 pownd32(_Decimal32 x, <del>intmax_t</del><ins>long long int</ins> n);
  _Decimal64 pownd64(_Decimal64 x, <del>intmax_t</del><ins>long long int</ins> n);
  _Decimal128 pownd128(_Decimal128 x, <del>intmax_t</del><ins>long long int</ins> n);
  #endif
</code>
</pre>
  </blockquote>

  <p>Change</p>

  <blockquote>
    <pre>
<code>
7.12.7.8 The rootn functions
Synopsis
1 #include <stdint.h>
  #include <math.h>
  double rootn(double x, intmax_t n);
  float rootnf(float x, intmax_t n);
  long double rootnl(long double x, intmax_t n);
  #ifdef __STDC_IEC_60559_DFP__
  _Decimal32 rootnd32(_Decimal32 x, intmax_t n);
  _Decimal64 rootnd64(_Decimal64 x, intmax_t n);
  _Decimal128 rootnd128(_Decimal128 x, intmax_t n);
  #endif
</code>
</pre>
  </blockquote>

  <p>to</p>

  <blockquote>
    <pre>
<code>
7.12.7.8 The rootn functions
Synopsis
1 #include <stdint.h>
  #include <math.h>
  double rootn(double x, <del>intmax_t</del><ins>long long int</ins> n);
  float rootnf(float x, <del>intmax_t</del><ins>long long int</ins> n);
  long double rootnl(long double x, <del>intmax_t</del><ins>long long int</ins> n);
  #ifdef __STDC_IEC_60559_DFP__
  _Decimal32 rootnd32(_Decimal32 x, <del>intmax_t</del><ins>long long int</ins> n);
  _Decimal64 rootnd64(_Decimal64 x, <del>intmax_t</del><ins>long long int</ins> n);
  _Decimal128 rootnd128(_Decimal128 x, <del>intmax_t</del><ins>long long int</ins> n);
  #endif
</code>
</pre>
  </blockquote>

  <p>For all of the above, also update the prototypes in Annex
  B.</p>
</body>
</html>