GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — Have math.isnormal() and, perhaps, math.issubnormal()? · Issue #132908 · python/cpython

Have math.isnormal() and, perhaps, math.issubnormal()? #132908

New issue
Copy link
New issue
Copy link
Closed
Closed
Have math.isnormal() and, perhaps, math.issubnormal()?#132908
Copy link
Labels
extension-modulesC modules in the Modules dirC modules in the Modules dirtype-featureA feature request or enhancementA feature request or enhancement

Description

@skirpichev
skirpichev
opened on Apr 25, 2025
Issue body actions

Feature or enhancement

Proposal:

Of course, these functions can be emulated in pure-Python.

On another hand, people can reasonably expect these classifiers as "The math module consists mostly of thin wrappers around the platform C math library functions." (c) isnormal() was in libm since C99 and issubnormal() - since C23.

Has this already been discussed elsewhere?

This is a minor feature, which does not need previous discussion elsewhere

Links to previous discussion of this feature:

No response

Linked PRs

  • gh-132908: Add math.isnormal/issubnormal() functions #132935
  • gh-132908: check the return type of isnormal() and issubnormal() #136039

Activity

Next
  1. skirpichev
    added
    extension-modulesC modules in the Modules dirC modules in the Modules dir
    type-featureA feature request or enhancementA feature request or enhancement
    on Apr 25, 2025
  2. skirpichev
    self-assigned this
    on Apr 25, 2025
  3. picnixz commented on Apr 25, 2025

    @picnixz
    picnixz
    on Apr 25, 2025
    Member
    More actions

    I once needed to know about whether a number is subnormal() so I would be happy to have it but... I think it's niche and numpy already proposes finfo for that so... I think users can live with this (big!) dependency if they already work with normal and subnormal numbers.

    For isnormal(), if it's part of C99, I'd say why not because we're a "thin wrapper" but for issubnormal(), it'd be only available on platforms that compiled Python with C23 (unless you want to rewrite issubnormal()?)

  4. skirpichev commented on Apr 25, 2025

    @skirpichev
    skirpichev
    on Apr 25, 2025
    MemberAuthor
    More actions

    I think users can live with this (big!) dependency if they already work with normal and subnormal numbers.

    This is something more basic and is a part of libm.

    For isnormal(), if it's part of C99, I'd say why not

    Yes, it's essentially a free lunch.

    but for issubnormal(), it'd be only available on platforms that compiled Python with C23

    I think we can check compiler conformance and if C23 support is missing - provide a simple replacement in terms of isfinite() & isnormal().

  5. skirpichev
    added a commit that references this issue on Apr 25, 2025

    pythongh-132908: add math.normal/subnormal() functions

    9d14505
  6. skirpichev
    removed their assignment
    on Apr 25, 2025
  7. skirpichev commented on Apr 25, 2025

    @skirpichev
    skirpichev
    on Apr 25, 2025
    MemberAuthor
    More actions

    PR is ready to review: #132935

  8. rhettinger commented on Apr 25, 2025

    @rhettinger
    rhettinger
    on Apr 25, 2025
    Contributor
    More actions

    I suggest leaving these out until there is a demonstrated user need.

    Unless people actually need this (I never have), it becomes module clutter than gets in the way of finding "the good stuff". We shouldn't add cognitive loads (one more thing to learn and remember) unless we expect a payoff.

  9. skirpichev commented on Apr 25, 2025

    @skirpichev
    skirpichev
    on Apr 25, 2025
    MemberAuthor
    More actions

    I suggest leaving these out until there is a demonstrated user need.

    If bugreport is a demonstration of "used needs" - here it is.

    SO example: https://stackoverflow.com/questions/59277521

    it becomes module clutter than gets in the way of finding "the good stuff".

    On the other hand, people can expect this from the libm wrapper. This time, rather than reinventing the wheel - I filled this bugreport.

  10. skirpichev
    added
    pendingThe issue will be closed if no feedback is providedThe issue will be closed if no feedback is provided
    on Apr 28, 2025
  11. skirpichev commented on Apr 28, 2025

    @skirpichev
    skirpichev
    on Apr 28, 2025
    MemberAuthor
    More actions

    I'm going to close this, on ground of Raymond's feedback.

    @tim-one ?

  12. tim-one commented on Apr 28, 2025

    @tim-one
    tim-one
    on Apr 28, 2025
    Member
    More actions

    Contrary to closing it, I'd like to see it expanded to include fpclassify() too :smile. The math module always intended to be a superset of the standard C libm functions, and C has grown, and math has generally kept up with it (albeit with a lag).

    Alas, it looks like although "even Microsoft" supports isnormal() and fpclassify() now, 'issubnormal()` appears to be missing.

    I don't find Raymond's objection persuasive in this case. It's not like we're making them up - they're very widely implemented already (comes with being part of standard C), the names are bizarre enough that if's dead easy to find detailed docs with a web search, and they're not at all hard to understand. Indeed, the names are darned near self-explanatory

    Ironically, I would have used these things yesterday, while writing a saner ldexp() for Windows. Instead I mucked around with frexp() to pick out the exponent to compare it with magical constants.

    Which I appreciate is more in the area of writing math libraries than end-user apps. I don't think they'll be widely used. But there's another kind of cognitive burden in trying to remember which near-universally supported math functions Python thinks are beneath its attention 😉.

    Reacted by Sergey B Kirpichev
  13. skirpichev
    removed
    pendingThe issue will be closed if no feedback is providedThe issue will be closed if no feedback is provided
    on Apr 28, 2025
  14. skirpichev commented on May 1, 2025

    @skirpichev
    skirpichev
    on May 1, 2025
    MemberAuthor
    More actions

    I'd like to see it expanded to include fpclassify()

    I was thinking about, but I don't see good arguments beyond "libm has it". After all, we don't have every math.h's functions exposed in the module (e.g. scalbn or logb).

    "even Microsoft" supports isnormal() and fpclassify() now, 'issubnormal()` appears to be missing.

    issubnormal() is a part of C23, which MSVC doesn't support yet.

  15. 2 remaining items

  16. serhiy-storchaka
    added a commit that references this issue on Jun 2, 2025

    gh-132908: Add math.isnormal/issubnormal() functions (GH132935)

    5f61cde
  17. serhiy-storchaka
    closed this as completedon Jun 2, 2025
  18. nineteendo commented on Jun 6, 2025

    @nineteendo
    nineteendo
    on Jun 6, 2025
    Contributor
    More actions

    Aren't we missing cmath.isnormal() and cmath.issubnormal()?

    • isnormal(z): Check if ALL components of z are normal
    • issubnormal(z): Check if ANY component of z is subnormal
  19. skirpichev commented on Jun 6, 2025

    @skirpichev
    skirpichev
    on Jun 6, 2025
    MemberAuthor
    More actions

    The C99+ Annex G doesn't define anything like that.

    Though, it also doesn't include isfinite (or isinf/isnan). But it says:

    A complex or imaginary value with at least one infinite part is regarded as an infinity (even if its
    other part is a NaN). A complex or imaginary value is a finite number if each of its parts is a finite
    number (neither infinite nor NaN).

    That's exactly - Python's isfinite/isinf. The isnan() in Python looks as an extension. But I doubt that isnormal() for complex numbers can be defined like that.

  20. nineteendo commented on Jun 6, 2025

    @nineteendo
    nineteendo
    on Jun 6, 2025
    Contributor
    More actions

    Great, different programming languages disagree on this:

    • .NET:
    public static bool IsNormal(Complex value)
    {
        // much as IsFinite requires both part to be finite, we require both
        // part to be "normal" (finite, non-zero, and non-subnormal) to be true
        return double.IsNormal(value.m_real) && ((value.m_imaginary == 0.0) || double.IsNormal(value.m_imaginary));
    }
    
    public static bool IsSubnormal(Complex value)
    {
        // much as IsInfinite allows either part to be infinite, we allow either
        // part to be "subnormal" (finite, non-zero, and non-normal) to be true
        return double.IsSubnormal(value.m_real) || double.IsSubnormal(value.m_imaginary);
    }
    • Swift:
      /// True if this value is normal.
      ///
      /// A complex number is normal if it is finite and *either* the real or
      /// imaginary component is normal. A floating-point number representing
      /// one of the components is normal if its exponent allows a full-precision
      /// representation.
      ///
      /// See also `.isFinite`, `.isSubnormal` and `.isZero`.
      @_transparent
      public var isNormal: Bool {
        isFinite && (x.isNormal || y.isNormal)
      }
      
      /// True if this value is subnormal.
      ///
      /// A complex number is subnormal if it is finite, not normal, and not zero.
      /// When the result of a computation is subnormal, underflow has occurred and
      /// the result generally does not have full precision.
      ///
      /// See also `.isFinite`, `.isNormal` and `.isZero`.
      @_transparent
      public var isSubnormal: Bool {
        isFinite && !isNormal && !isZero
      }
  21. skirpichev commented on Jun 7, 2025

    @skirpichev
    skirpichev
    on Jun 7, 2025
    MemberAuthor
    More actions

    No doubts, you can define such notions. But note, that your definitions are different.

    The C99 standard rationale shows arguments for isinf/isnan, e.g.:

    Image

    Which arguments for using either definition of isnormal() for complex numbers? Is this useful? Why? M$ version is especially odd as asymmetrical wrt components.

  22. nineteendo commented on Jun 7, 2025

    @nineteendo
    nineteendo
    on Jun 7, 2025
    Contributor
    More actions

    isnormal(z) = isnormal(z.real) and isnormal(z.imag):

    • performance:
    $ python -m timeit -s "a = 2+0j; b = 5e-308+5e-308j" "a * b"
    5000000 loops, best of 5: 49.1 nsec per loop
    $ python -m timeit -s "a = 2+0j; b = 5e-308+5e-324j" "a * b"
    5000000 loops, best of 5: 88.3 nsec per loop
    $ python -m timeit -s "a = 2+0j; b = 5e-324+5e-324j" "a * b"
    2000000 loops, best of 5: 124 nsec per loop
    • accuracy:
    >>> (5e-308+5e-308j) * 1e308
    (5+5j)
    >>> (5e-308+5e-324j) * 1e308
    (5+4.9406564584124655e-16j)
    >>> (5e-324+5e-324j) * 1e308
    (4.9406564584124655e-16+4.9406564584124655e-16j)
    • Neither component is denormalized

    Do you see an argument for the other definition? Or should we give that a different name?
    isnormal(z) = isfinite(z) and (isnormal(z.real) or isnormal(z.imag))

  23. skirpichev commented on Jun 7, 2025

    @skirpichev
    skirpichev
    on Jun 7, 2025
    MemberAuthor
    More actions

    Sorry, could be elaborate your "performance" and "accuracy" arguments?

  24. nineteendo commented on Jun 7, 2025

    @nineteendo
    nineteendo
    on Jun 7, 2025
    Contributor
    More actions

    I'm mostly trying to compare it with the reasons for having std::isnormal(x).

    • Most CPU's handle subnormal numbers much more slowly than normals. A simple multipliction by 2, can be up to 2.53x slower (compared to 1.15x slower for infinities). I expect a similar story for other operations.
    • When you get a subnormal number after multiplication, you lose precision in later operations.

    So, raising an error in these cases using isnormal() could make sense.

  25. skirpichev commented on Jun 7, 2025

    @skirpichev
    skirpichev
    on Jun 7, 2025
    MemberAuthor
    More actions

    Yes, but I don't see yet arguments for a concrete isnormal() definition for complex.

  26. nineteendo commented on Jun 7, 2025

    @nineteendo
    nineteendo
    on Jun 7, 2025
    Contributor
    More actions

    Maybe we should discuss this on Discourse?

  27. skirpichev commented on Jun 7, 2025

    @skirpichev
    skirpichev
    on Jun 7, 2025
    MemberAuthor
    More actions

    Feel free to do so .
    I'm not sure if it worth, I am -0 on this.

  28. Pranjal095
    added a commit that references this issue on Jul 12, 2025

    pythongh-132908: Add math.isnormal/issubnormal() functions (GH132935)

    9c8bb06
  29. taegyunkim
    added a commit that references this issue on Aug 4, 2025

    pythongh-132908: Add math.isnormal/issubnormal() functions (GH132935)

    0e20787
  30. Agent-Hellboy
    added a commit that references this issue on Aug 19, 2025

    pythongh-132908: Add math.isnormal/issubnormal() functions (GH132935)

    6d99e88
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    extension-modulesC modules in the Modules dirC modules in the Modules dirtype-featureA feature request or enhancementA feature request or enhancement

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

      You are visitor 01402503 — GeezerVison does not store the pages you look up.
      Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.