<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40"><head><meta http-equiv=Content-Type content="text/html; charset=utf-8"><meta name=Generator content="Microsoft Word 15 (filtered medium)"><style><!--
/* Font Definitions */
@font-face
        {font-family:"Cambria Math";
        panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0in;
        margin-bottom:.0001pt;
        font-size:12.0pt;
        font-family:"Times New Roman",serif;}
a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:blue;
        text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
        {mso-style-priority:99;
        color:purple;
        text-decoration:underline;}
p.msonormal0, li.msonormal0, div.msonormal0
        {mso-style-name:msonormal;
        mso-margin-top-alt:auto;
        margin-right:0in;
        mso-margin-bottom-alt:auto;
        margin-left:0in;
        font-size:12.0pt;
        font-family:"Times New Roman",serif;}
span.EmailStyle18
        {mso-style-type:personal-reply;
        font-family:"Calibri",sans-serif;
        color:windowtext;}
.MsoChpDefault
        {mso-style-type:export-only;
        font-family:"Calibri",sans-serif;}
@page WordSection1
        {size:8.5in 11.0in;
        margin:1.0in 1.0in 1.0in 1.0in;}
div.WordSection1
        {page:WordSection1;}
--></style><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1" />
</o:shapelayout></xml><![endif]--></head><body lang=EN-US link=blue vlink=purple><div class=WordSection1><p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri",sans-serif'>The presence of the function in C99’s math.h isn’t strictly useful unless it is also in the MSVC math.h.  MSVC only supports a subset of C99<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:11.0pt;font-family:"Calibri",sans-serif'><o:p> </o:p></span></p><div style='border:none;border-left:solid blue 1.5pt;padding:0in 0in 0in 4.0pt'><div><div style='border:none;border-top:solid #E1E1E1 1.0pt;padding:3.0pt 0in 0in 0in'><p class=MsoNormal><b><span style='font-size:11.0pt;font-family:"Calibri",sans-serif'>From:</span></b><span style='font-size:11.0pt;font-family:"Calibri",sans-serif'> Python-ideas [mailto:python-ideas-bounces+tritium-list=sdamon.com@python.org] <b>On Behalf Of </b>Juraj Sukop<br><b>Sent:</b> Saturday, February 4, 2017 6:31 AM<br><b>To:</b> python-ideas@python.org<br><b>Subject:</b> [Python-ideas] math.nextafter<o:p></o:p></span></p></div></div><p class=MsoNormal><o:p> </o:p></p><div><div><p class=MsoNormal>Hello!<o:p></o:p></p></div><div><p class=MsoNormal><o:p> </o:p></p></div><div><p class=MsoNormal>Function `nextafter(x, y)` returns the next representable value of `x` in the direction of `y`, and if `x` equals to `y`, `y` is returned. [1]<o:p></o:p></p></div><div><p class=MsoNormal><o:p> </o:p></p></div><div><p class=MsoNormal>It is useful for incrementing/decrementing floating-point number by the smallest amount possible or for testing if two numbers are closest to each other without being the same.<o:p></o:p></p></div><div><p class=MsoNormal><o:p> </o:p></p></div><div><p class=MsoNormal>The following snippet written by Mark Dickinson emulates the functionality in pure Python [2]:<o:p></o:p></p></div><div><p class=MsoNormal><o:p> </o:p></p></div><div><p class=MsoNormal>    import math<o:p></o:p></p></div><div><p class=MsoNormal>    import struct<o:p></o:p></p></div><div><p class=MsoNormal><o:p> </o:p></p></div><div><p class=MsoNormal>    def next_up(x):<o:p></o:p></p></div><div><p class=MsoNormal>        # NaNs and positive infinity map to themselves.<o:p></o:p></p></div><div><p class=MsoNormal>        if math.isnan(x) or (math.isinf(x) and x > 0):<o:p></o:p></p></div><div><p class=MsoNormal>            return x<o:p></o:p></p></div><div><p class=MsoNormal><o:p> </o:p></p></div><div><p class=MsoNormal>        # 0.0 and -0.0 both map to the smallest +ve float.<o:p></o:p></p></div><div><p class=MsoNormal>        if x == 0.0:<o:p></o:p></p></div><div><p class=MsoNormal>            x = 0.0<o:p></o:p></p></div><div><p class=MsoNormal><o:p> </o:p></p></div><div><p class=MsoNormal>        n = struct.unpack('<q', struct.pack('<d', x))[0]<o:p></o:p></p></div><div><p class=MsoNormal>        if n >= 0:<o:p></o:p></p></div><div><p class=MsoNormal>            n += 1<o:p></o:p></p></div><div><p class=MsoNormal>        else:<o:p></o:p></p></div><div><p class=MsoNormal>            n -= 1<o:p></o:p></p></div><div><p class=MsoNormal>        return struct.unpack('<d', struct.pack('<q', n))[0]<o:p></o:p></p></div><div><p class=MsoNormal>    <o:p></o:p></p></div><div><p class=MsoNormal>    def next_down(x):<o:p></o:p></p></div><div><p class=MsoNormal>        return -next_up(-x)<o:p></o:p></p></div><div><p class=MsoNormal><o:p> </o:p></p></div><div><p class=MsoNormal>    def next_after(x, y):<o:p></o:p></p></div><div><p class=MsoNormal>        # If either argument is a NaN, return that argument.<o:p></o:p></p></div><div><p class=MsoNormal>        # This matches the implementation in decimal.Decimal<o:p></o:p></p></div><div><p class=MsoNormal>        if math.isnan(x):<o:p></o:p></p></div><div><p class=MsoNormal>            return x<o:p></o:p></p></div><div><p class=MsoNormal>        if math.isnan(y):<o:p></o:p></p></div><div><p class=MsoNormal>            return y<o:p></o:p></p></div><div><p class=MsoNormal><o:p> </o:p></p></div><div><p class=MsoNormal>        if y == x:<o:p></o:p></p></div><div><p class=MsoNormal>            return y<o:p></o:p></p></div><div><p class=MsoNormal>        elif y > x:<o:p></o:p></p></div><div><p class=MsoNormal>            return next_up(x)<o:p></o:p></p></div><div><p class=MsoNormal>        else:<o:p></o:p></p></div><div><p class=MsoNormal>            return next_down(x)<o:p></o:p></p></div><div><p class=MsoNormal><o:p> </o:p></p></div><div><p class=MsoNormal>Other implementations can be found at [3], [4] or [5], for example.<o:p></o:p></p></div><div><p class=MsoNormal><o:p> </o:p></p></div><div><p class=MsoNormal>It would be useful to have `math.nextafter` function available in standard library, it also is provided by C99 <math.h>, and is similar in spirit to `math.copysign` or `math.isclose`.<o:p></o:p></p></div><div><p class=MsoNormal><o:p> </o:p></p></div><div><p class=MsoNormal>As to why to include it by default when the above snippet works just fine, a C implementation is likely to be much faster than using `struct.pack` and `struct.unpack`.<o:p></o:p></p></div><div><p class=MsoNormal><o:p> </o:p></p></div><div><p class=MsoNormal>Thank you for considering this proposal and any feedback is greatly welcomed!<o:p></o:p></p></div><div><p class=MsoNormal><o:p> </o:p></p></div><div><p class=MsoNormal>Juraj Sukop<o:p></o:p></p></div><div><p class=MsoNormal><o:p> </o:p></p></div><div><p class=MsoNormal>[1] <a href="http://en.cppreference.com/w/c/numeric/math/nextafter">http://en.cppreference.com/w/c/numeric/math/nextafter</a><o:p></o:p></p></div><div><p class=MsoNormal>[2] <a href="http://stackoverflow.com/a/10426033">http://stackoverflow.com/a/10426033</a><o:p></o:p></p></div><div><p class=MsoNormal>[3] <a href="http://git.musl-libc.org/cgit/musl/tree/src/math/nextafter.c">http://git.musl-libc.org/cgit/musl/tree/src/math/nextafter.c</a><o:p></o:p></p></div><div><p class=MsoNormal>[4] <a href="https://github.com/android/platform_bionic/blob/master/libm/upstream-freebsd/lib/msun/src/s_nextafter.c">https://github.com/android/platform_bionic/blob/master/libm/upstream-freebsd/lib/msun/src/s_nextafter.c</a><o:p></o:p></p></div><div><p class=MsoNormal>[5] <a href="https://github.com/golang/go/blob/master/src/math/nextafter.go">https://github.com/golang/go/blob/master/src/math/nextafter.go</a><o:p></o:p></p></div><div><p class=MsoNormal><o:p> </o:p></p></div></div></div></div></body></html>