# Negative false no longer acts as a strong zero

**URL:** <https://discourse.julialang.org/t/negative-false-no-longer-acts-as-a-strong-zero/128506>\
**Category:** General Usage\
**Created:** [April 28, 2025, 11:35pm UTC](https://discourse.julialang.org/t/negative-false-no-longer-acts-as-a-strong-zero/128506 "2025-04-28T23:35:48Z")\
**Posts on this page:** 4\
**Page:** 2

<div class="post-metadata">

**Author:** ![tam724](https://avatars.discourse-cdn.com/v4/letter/t/e36b37/32.png) [@tam724](https://discourse.julialang.org/u/tam724)\
**Post date:** [July 3, 2025, 8:57am UTC](https://discourse.julialang.org/t/negative-false-no-longer-acts-as-a-strong-zero/128506/21 "2025-07-03T08:57:34Z")

</div>

Thanks for bringing this to the discussion @lance_xwq !  
Here’s a follow up: How consistent should the `NaN*false` behaviour be treated? As an example:

```julia
julia> using LinearAlgebra

julia> x, A, y = fill(NaN32, 2), fill(NaN32, 2, 2), fill(NaN32, 2)
(Float32[NaN, NaN], Float32[NaN NaN; NaN NaN], Float32[NaN, NaN])

julia> mul!(y, A, x, false, false) # stops the NaN propagation
2-element Vector{Float32}:
 0.0
 0.0

julia> x, A, y = fill(NaN16, 2), fill(NaN16, 2, 2), fill(NaN16, 2)
(Float16[NaN, NaN], Float16[NaN NaN; NaN NaN], Float16[NaN, NaN])

julia> mul!(y, A, x, false, false) # does NOT stop the NaN's
2-element Vector{Float16}:
 NaN
 NaN

julia> X, A, Y = fill(NaN16, 2, 2), fill(NaN16, 2, 2), fill(NaN16, 2, 2)
(Float16[NaN NaN; NaN NaN], Float16[NaN NaN; NaN NaN], Float16[NaN NaN; NaN NaN])

julia> mul!(Y, A, X, false, false) # however, matmatmul does
2×2 Matrix{Float16}:
 0.0 0.0
 0.0 0.0

```

Is this worth an issue?

---

<div class="post-metadata">

**Author:** ![jishnub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jishnub/32/33620_2.png) [@jishnub](https://discourse.julialang.org/u/jishnub)\
**Post date:** [July 3, 2025, 10:40am UTC](https://discourse.julialang.org/t/negative-false-no-longer-acts-as-a-strong-zero/128506/22 "2025-07-03T10:40:20Z")

</div>

Yes, please file an issue in LinearAlgebra.jl

---

<div class="post-metadata">

**Author:** ![foobar\_lv2](https://avatars.discourse-cdn.com/v4/letter/f/ee59a6/32.png) [@foobar\_lv2](https://discourse.julialang.org/u/foobar_lv2)\
**Post date:** [July 3, 2025, 10:47am UTC](https://discourse.julialang.org/t/negative-false-no-longer-acts-as-a-strong-zero/128506/23 "2025-07-03T10:47:24Z")

</div>

> [@tam724](#):
>
> Is this worth an issue?

Yes. This is a bug.

The implementation of `__generic_matvecmul!(::typeof(identity), C::AbstractVector, A::AbstractVecOrMat, B::AbstractVector, alpha::Number, beta::Number)` appears to be plain wrong.

The issue is that `x * (NaN * false) != (x * NaN) * false` for `x=NaN` and the code re-associates the latter into the former, in order to loop-hoist one multiplication.

This messes up all matmuls with non-associative multiplication that are not saved by specialized implementations.

The appropriate thing is to have a check for `beta == false`, because that allows us to also save a lot of time. I would go even further and have a check for `iszero(beta)` and `iszero(alpha)`, and document that `mul!(C, A, B, alpha, beta)` is permitted (but not obligated) to treat vanishing alpha, beta as strong zeros.

Also, `false*missing === missing` is silly.

---

<div class="post-metadata">

**Author:** ![tam724](https://avatars.discourse-cdn.com/v4/letter/t/e36b37/32.png) [@tam724](https://discourse.julialang.org/u/tam724)\
**Post date:** [July 3, 2025, 11:06am UTC](https://discourse.julialang.org/t/negative-false-no-longer-acts-as-a-strong-zero/128506/24 "2025-07-03T11:06:19Z")

</div>

> <https://github.com/JuliaLang/LinearAlgebra.jl/issues/1399>
>
> For e.g. \`Float16\` where \`mul!\` (mat-vec) does not call BLAS, but the generic ju…lia implementation, the resulting vector after \`mul!\` with \`α, β = false, false\` still contains \`NaN\`s.
> Here's a MWE:
> \`\`\`
> julia\> using LinearAlgebra
> 
> julia\> x, A, y = fill(NaN32, 2), fill(NaN32, 2, 2), fill(NaN32, 2)
> (Float32\[NaN, NaN\], Float32\[NaN NaN; NaN NaN\], Float32\[NaN, NaN\])
> 
> julia\> mul!(y, A, x, false, false) # stops the NaN propagation
> 2-element Vector{Float32}:
> 0.0
> 0.0
> 
> julia\> x, A, y = fill(NaN16, 2), fill(NaN16, 2, 2), fill(NaN16, 2)
> (Float16\[NaN, NaN\], Float16\[NaN NaN; NaN NaN\], Float16\[NaN, NaN\])
> 
> julia\> mul!(y, A, x, false, false) # does NOT stop the NaN's
> 2-element Vector{Float16}:
> NaN
> NaN
> 
> julia\> X, A, Y = fill(NaN16, 2, 2), fill(NaN16, 2, 2), fill(NaN16, 2, 2)
> (Float16\[NaN NaN; NaN NaN\], Float16\[NaN NaN; NaN NaN\], Float16\[NaN NaN; NaN NaN\])
> 
> julia\> mul!(Y, A, X, false, false) # however, matmatmul does
> 2×2 Matrix{Float16}:
> 0.0 0.0
> 0.0 0.0
> \`\`\`
> I tried with julia 1.11.5 and 1.12.0-beta4.

[Previous page](https://discourse.julialang.org/t/negative-false-no-longer-acts-as-a-strong-zero/128506.md?page=1)
