# Hypot is not consistent?

**URL:** <https://discourse.julialang.org/t/hypot-is-not-consistent/138663>\
**Category:** General Usage\
**Tags:** effects\
**Created:** [August 7, 2026, 3:43pm UTC](https://discourse.julialang.org/t/hypot-is-not-consistent/138663 "2026-08-07T15:43:37Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![ettersi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ettersi/32/6829_2.png) [@ettersi](https://discourse.julialang.org/u/ettersi)\
**Post date:** [August 7, 2026, 3:43pm UTC](https://discourse.julialang.org/t/hypot-is-not-consistent/138663/1 "2026-08-07T15:43:37Z")

</div>

Just saw this:

```julia-auto
julia> Base.infer_effects(hypot, NTuple{2, Float64})
(!c,+e,!n,+t,+s,+m,+u,+o,+r)

```

How come `hypot()` is not consistent? Is this a problem of inference not being precise, or is there actually something that makes `hypot()` inconsistent?

`hypot()` not being consistent doesn’t really matter to me, just curious…

---

<div class="post-metadata">

**Author:** ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)\
**Post date:** [August 7, 2026, 3:53pm UTC](https://discourse.julialang.org/t/hypot-is-not-consistent/138663/2 "2026-08-07T15:53:56Z")

</div>

We produce different results depending on whether your CPU has FMA.

---

<div class="post-metadata">

**Author:** ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)\
**Post date:** [August 7, 2026, 3:57pm UTC](https://discourse.julialang.org/t/hypot-is-not-consistent/138663/3 "2026-08-07T15:57:51Z")

</div>

Shouldn’t these `effects` results be for a given CPU target though?

---

<div class="post-metadata">

**Author:** ![simeonschaub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/simeonschaub/32/216566_2.png) [@simeonschaub](https://discourse.julialang.org/u/simeonschaub)\
**Post date:** [August 7, 2026, 3:58pm UTC](https://discourse.julialang.org/t/hypot-is-not-consistent/138663/4 "2026-08-07T15:58:34Z")

</div>

You can actually track this down yourself using Cthulhu.jl. Specifically, if you do `descend_code_typed(Base.Math._hypot, NTuple{2, Float64}; effects = true)`, you can see that on line 769 there is a call to `Intrinsics.have_fma`, which taints the `consistent` effect bit:

```julia-auto
│ @ math.jl:769 within `unknown scope`
│ %134 = Base.Math.Core::Core.Const(Core) (+c,+e,+n,+t,+s,+m,+u,+o,+r)
│ %135 = dynamic Base.getproperty(%134, :Intrinsics)::Core.Const(Core.Intrinsics) (+c,+e,+n,+t,+s,+m,+u,+o,+r)
│ %136 = dynamic Base.getproperty(%135, :have_fma)::Core.Const(Core.Intrinsics.have_fma) (+c,+e,+n,+t,+s,+m,+u,+o,+r)
│ %137 = Base.Math.typeof::Core.Const(typeof) (+c,+e,+n,+t,+s,+m,+u,+o,+r)
│ %138 = h::Float64 (+c,+e,+n,+t,+s,+m,+u,+o,+r)
│ %139 = builtin (%137)(%138)::Core.Const(Float64) (+c,+e,+n,+t,+s,+m,+u,+o,+r)
│ %140 = intrinsic (%136)(%139)::Bool (!c,+e,+n,+t,+s,+m,+u,+o,+r)
└─── goto #16 if not %140 (+c,+e,+n,+t,+s,+m,+u,+o,+r)

```

To expand on Oscar’s answer, that `have_fma` call taints consistency due to the presence of multiversioning, where LLVM might compile this function for an architecture version that doesn’t have fma, so Julia’s compiler can’t assume `have_fma` always returns the same answer.

---

<div class="post-metadata">

**Author:** ![Palli](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/palli/32/3380_2.png) [@Palli](https://discourse.julialang.org/u/Palli)\
**Post date:** [August 7, 2026, 4:05pm UTC](https://discourse.julialang.org/t/hypot-is-not-consistent/138663/5 "2026-08-07T16:05:35Z")

</div>

I was investigating and I thought I had ruled out fma, or related muladd used for !c, but not for !n (nor for sqrt)…:

```julia-auto
julia> Base.infer_effects(muladd, NTuple{3, Float64})
(+c,+e,!n,+t,+s,+m,+u,+o,+r)

julia> Base.infer_effects(fma, NTuple{3, Float64})
(+c,+e,+n,+t,+s,+m,+u,+o,+r)

julia> Base.infer_effects(sqrt, NTuple{1, Float64})
(+c,+e,!n,+t,+s,+m,+u,+o,+r)

```

> [@simeonschaub](#):
>
> on line 769 there is a call to `Intrinsics.have_fma`, which taints the `consistent` effect bit:
> 
> ```julia-auto
> │ %136 = dynamic Base.getproperty(%135, :have_fma)::Core.Const(Core.Intrinsics.have_fma) (+c,+e,+n,+t,+s,+m,+u,+o,+r)
> 
> ```

Where do you read that from, is that the line to look at?! What does +c mean there as opposed to !c?

```julia-auto
Base.infer_effects(Core.Intrinsics.have_fma, NTuple{1, Float64}) # Core.Intrinsics.have_fma(typeof(h))
(!c,+e,!n,+t,+s,+m,+u,+o,+r)

```

---

<div class="post-metadata">

**Author:** ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)\
**Post date:** [August 7, 2026, 4:20pm UTC](https://discourse.julialang.org/t/hypot-is-not-consistent/138663/6 "2026-08-07T16:20:06Z")

</div>

How bad of an idea would it be for us to use `@assume_effects :consistent` on functions like `hypot`?

Would this cause actual miscompilation problems?

---

<div class="post-metadata">

**Author:** ![Palli](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/palli/32/3380_2.png) [@Palli](https://discourse.julialang.org/u/Palli)\
**Post date:** [August 7, 2026, 4:41pm UTC](https://discourse.julialang.org/t/hypot-is-not-consistent/138663/7 "2026-08-07T16:41:38Z")

</div>

> [@Mason](#):
>
> How bad of an idea would it be for us to use `@assume_effects :consistent` on functions like `hypot`?

That depends on what :consistent means, I think it means you get same output out for any input, and that happens if you have fma hardware, i.e. for most users. For the others they also get same answers for any input and i.e. same for all other _non-fma_ hardware users, the results for the `muladd` used in the else branch, just not bit-identical to the others on `fma` hardware because:

```julia-auto
    # This branch is correctly rounded but requires a native hardware fma.
    if Core.Intrinsics.have_fma(typeof(h))
        hsquared = h*h
        axsquared = ax*ax
        h -= (fma(-ay, ay, hsquared-axsquared) + fma(h, h,-hsquared) - fma(ax, ax, -axsquared))/(2*h)
    # This branch is within one ulp of correctly rounded.
    else

```

I’ve never seen code like this, I though muladd generally used, and it meant fma on such hardware, but the else branch is a bit different to compensate, but not fully. I’ve been investigating where we get correctly rounded, and if Julia should promise, this is an interesting case. Should Julia at least promise at least “within one ulp of correctly rounded”? And should docs of hypot mention this?

What is the practical effect of `!c`, then considered a non-pure function, and results not cached and reused? And if you lie with `@assume_effects :consistent` possibly sightly better code generation? But would some people or tools infer correctly rounded, or identical rounding to old platforms?
