Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add math.ulp(x): unit in the last place #83491

Closed
vstinner opened this issue Jan 12, 2020 · 14 comments
Closed

Add math.ulp(x): unit in the last place #83491

vstinner opened this issue Jan 12, 2020 · 14 comments
Labels
3.9 only security fixes stdlib Python modules in the Lib dir

Comments

@vstinner
Copy link
Member

BPO 39310
Nosy @tim-one, @brettcannon, @rhettinger, @mdickinson, @vstinner, @stevendaprano, @miss-islington
PRs
  • bpo-39310: Add math.ulp(x) #17965
  • [3.8] bpo-39310: Update sys.float_info documentation #17982
  • [3.7] bpo-39310: Update sys.float_info documentation (GH-17982) #17994
  • Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

    Show more details

    GitHub fields:

    assignee = None
    closed_at = <Date 2020-01-13.11:47:40.328>
    created_at = <Date 2020-01-12.12:33:34.419>
    labels = ['library', '3.9']
    title = 'Add math.ulp(x): unit in the last place'
    updated_at = <Date 2020-01-15.22:50:31.240>
    user = 'https://github.com/vstinner'

    bugs.python.org fields:

    activity = <Date 2020-01-15.22:50:31.240>
    actor = 'tim.peters'
    assignee = 'none'
    closed = True
    closed_date = <Date 2020-01-13.11:47:40.328>
    closer = 'vstinner'
    components = ['Library (Lib)']
    creation = <Date 2020-01-12.12:33:34.419>
    creator = 'vstinner'
    dependencies = []
    files = []
    hgrepos = []
    issue_num = 39310
    keywords = ['patch']
    message_count = 14.0
    messages = ['359846', '359859', '359882', '359883', '359891', '359898', '359927', '359929', '359937', '359938', '359939', '359940', '360032', '360082']
    nosy_count = 8.0
    nosy_names = ['tim.peters', 'brett.cannon', 'rhettinger', 'mark.dickinson', 'vstinner', 'stutzbach', 'steven.daprano', 'miss-islington']
    pr_nums = ['17965', '17982', '17994']
    priority = 'normal'
    resolution = 'fixed'
    stage = 'resolved'
    status = 'closed'
    superseder = None
    type = None
    url = 'https://bugs.python.org/issue39310'
    versions = ['Python 3.9']

    @vstinner
    Copy link
    Member Author

    In bpo-39288, I added math.nextafter(x, y) function. I propose to now add math.ulp() companion function.

    Examples from tests of my PR:

    self.assertEqual(math.ulp(1.0), sys.float_info.epsilon)
    self.assertEqual(math.ulp(2.0 ** 52), 1.0)
    self.assertEqual(math.ulp(2.0 ** 53), 2.0)
    self.assertEqual(math.ulp(2.0 ** 64), 4096.0)
    

    Unit in the last place:

    In numpy, I found two references to ULP:

    Attached PR implements math.ulp(x).

    @vstinner vstinner added 3.9 only security fixes stdlib Python modules in the Lib dir labels Jan 12, 2020
    @vstinner vstinner changed the title Add math.ulp(x) Add math.ulp(x): unit in the last place Jan 12, 2020
    @vstinner vstinner changed the title Add math.ulp(x) Add math.ulp(x): unit in the last place Jan 12, 2020
    @vstinner
    Copy link
    Member Author

    See also math.isclose() and its PEP-485 which mentions ULP (Unit in the Last Place)... in the "Inappropriate uses" section :-)

    Extract of an old python-ideas discussion on adding nextafter():

    "It's also a little weird to jump from nextafter to isclose, since AFAIK
    they have pretty much non-overlapping use cases..."

    https://mail.python.org/pipermail/python-ideas/2017-February/044832.html

    Other links:

    @tim-one
    Copy link
    Member

    tim-one commented Jan 13, 2020

    +1

    @stevendaprano
    Copy link
    Member

    Thank you Victor!

    Any chance you could look at fma too? bpo-29282

    (The reward for a job well done is to be given more jobs :-)

    @mdickinson
    Copy link
    Member

    [Steven]

    Any chance you could look at fma too? bpo-29282

    fma is hard, for reasons explained in the issue you linked to. If you have suggestions for resolving the difficulties, please do add them to that issue.

    @vstinner
    Copy link
    Member Author

    New changeset 0b2ab21 by Victor Stinner in branch 'master':
    bpo-39310: Add math.ulp(x) (GH-17965)
    0b2ab21

    @vstinner
    Copy link
    Member Author

    New changeset 9362f85 by Victor Stinner in branch '3.8':
    bpo-39310: Update sys.float_info documentation (GH-17982)
    9362f85

    @miss-islington
    Copy link
    Contributor

    New changeset dfe159c by Miss Islington (bot) in branch '3.7':
    bpo-39310: Update sys.float_info documentation (GH-17982)
    dfe159c

    @brettcannon
    Copy link
    Member

    Can I just say that "ulp" is totally non-obvious what that even means unless you have a specific math background?

    @brettcannon
    Copy link
    Member

    And sorry if that last response from me came off as grumpy; it wasn't meant to. I just had no clue what you were adding based on the name.

    @vstinner
    Copy link
    Member Author

    Can I just say that "ulp" is totally non-obvious what that even means unless you have a specific math background?

    The math.ulp() documentation explicitly says: https://docs.python.org/dev/library/math.html#math.ulp

    ULP stands for “Unit in the Last Place”.

    The term "ulp" is commonly used when talking about IEEE 754 floating point numbers. It is used in numpy and Java for example.

    test_math.py already had an ulp() function which was a pure Python implementation.

    The term is also commonly used in math articles.

    If you don't know the term "ulp", it's likely a *good thing*. You didn't have to suffer with rounding issues :-D

    @stevendaprano
    Copy link
    Member

    I hear what you are saying, but "ulp" is the standard term of art. Sure
    it is non-obvious until you learn it, just like other technical terms
    like "mro", "abc" or "ast".

    Mathematics and numeric programming are rife with short names that are
    non-obvious and often ambiguous with "ordinary" words, e.g.

    sin, tan, log, nan
    

    to mention just a few. "ulp" is a technical, and subtle, concept to
    grasp, and no easier to understand when spelled out as "unit in last
    place".

    At least ulp is a TLA from English, unlike (say) "sine" which ultimately
    derives from the Sanscrit word "jya" (chord), via Arabic and Latin. If
    you've ever wondered if the trigonometric sin() function is related to
    the sinus cavities in your nose, yes it is :-)

    @mdickinson
    Copy link
    Member

    [Brett]

    Can I just say that "ulp" is totally non-obvious what that even means unless you have a specific math background?

    It's a good point. I guess we have a choice between using the domain-specific standard-ish name (which should be immediately meaningful to experts, but doesn't give much of a hint to non-experts) or using something more descriptive (which then risks confusing experts until they figure out "oh, that's just ulp").

    There's also the option of spelling it out as "unit_in_last_place", but I'm not sure that benefits anyone.

    For meaningful descriptive names, "float_resolution" or "gap_to_next" are about the best I can come up with. "precision" is too ambiguous.

    NumPy has "numpy.spacing". But this exhibits exactly the trap of not using the "ulp" name: on a first glance, I incorrectly decided that NumPy didn't implement a ulp function. Then, having found numpy.spacing, I had to read the description carefully in order to recognise that "oh, this is just ulp". (Actually, I had to do more, since the description doesn't make all the corner cases clear, and in fact is currently wrong for powers of 2.)

    If we can get people can coalesce around a preferred alternative name, we could consider changing this.

    @tim-one
    Copy link
    Member

    tim-one commented Jan 15, 2020

    ulp() is the right name: universally understood by those who know how to use it, and easy to find exhaustive web explanations for those who don't.

    In a different context, spelling out some variant of Hypertext_Transfer_Protocol would be as wrong-headed to avoid the "cryptic" http.

    @ezio-melotti ezio-melotti transferred this issue from another repository Apr 10, 2022
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Labels
    3.9 only security fixes stdlib Python modules in the Lib dir
    Projects
    None yet
    Development

    No branches or pull requests

    6 participants