# zero(a::Real)?

**URL:** <https://discourse.julialang.org/t/zero-a-real/107175>\
**Category:** General Usage\
**Tags:** question, type, zeros\
**Created:** [December 5, 2023, 3:25pm UTC](https://discourse.julialang.org/t/zero-a-real/107175 "2023-12-05T15:25:31Z")\
**Posts on this page:** 5\
**Page:** 2

<div class="post-metadata">

**Author:** ![ryofurue](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ryofurue/32/24531_2.png) [@ryofurue](https://discourse.julialang.org/u/ryofurue)\
**Post date:** [December 6, 2023, 1:49am UTC](https://discourse.julialang.org/t/zero-a-real/107175/21 "2023-12-06T01:49:54Z")

</div>

> [@mikmoore](#):
>
> `zero(r/r)` is a suitable zero.

Wonderful! I’ve just confirmed that that works perfectly for my code. As you say, that’s because `somefunction(r)` returns the same type as `r`.

In addition,

> [@mikmoore](#):
>
> ```julia
> func(r) = someotherfunction(r) / r * !iszero(r)
> func(r) = iszero(r) ? zero(r/r) : someotherfunction(r)/r
> func(r) = iszero(r) ? someotherfunction(zero(r))/one(r) : someotherfunction(r)/r
> 
> ```

the second one is the clearest: it’s easiest to guess the intention of the code.

---

<div class="post-metadata">

**Author:** ![ryofurue](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ryofurue/32/24531_2.png) [@ryofurue](https://discourse.julialang.org/u/ryofurue)\
**Post date:** [December 6, 2023, 2:49am UTC](https://discourse.julialang.org/t/zero-a-real/107175/22 "2023-12-06T02:49:07Z")

</div>

> [@Palli](#):
>
> It was a “bug” in _your_ code, i.e. it not type stable (that’s not illegal so bug may be the wrong word, at least surprising), but with it giving 0.0, i.e. Float64, it seemingly wouldn’t have been. So is it a bug in Julia?

I thought about this some more, and perhaps I should say that this is _a sort of_ bug in Julia, although it may not be fixable.

> [@Palli](#):
>
> > [@ryofurue](#):
> >
> > Normally I avoid “0.0”, not to unnecessarily narrow the range of types that work with my functions.
> 
> That’s very good practice to avoid non-general code, but then you must also avoid 0.

So, the community advocates generic code, while the language doesn’t provide an easy means to achieve that. I’d love to avoid the concretely-typed literal `0` but how?

@mikmoore found a nice solution for my case (`zero(r/r)`) . . . is this then what everybody should write?

To put this in another way, what examples would you show if you were writing a tutorial for newcomers. From this discussion, I would be tempted to recommend this style

```julia
func(r) = iszero(r) ? zero(r/r) : somefunction(r)/r

```

with some caveats regarding when this doesn’t work as intended.

But, for newcomers, this is too obscure. You’d rather write an example like

```julia
func(r) = (r == 0) ? 0 : somefunction(r)/r

```

and most “ordinary” programmers would stay there.

---

<div class="post-metadata">

**Author:** ![Dan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dan/32/42581_2.png) [@Dan](https://discourse.julialang.org/u/Dan)\
**Post date:** [December 6, 2023, 4:54am UTC](https://discourse.julialang.org/t/zero-a-real/107175/23 "2023-12-06T04:54:49Z")

</div>

> [@ryofurue](#):
>
> ```julia
> function(a, b) 
> res = zero(a) # initialize with zeros.
> for i = eachindex(a), j = eachindex(b)
> res[i] += function_of(b[j]) # inexact error: Int(1.123456e-16)
> end
> return res
> end
> 
> ```

Also, semantically, perhaps the pedantic way would be to initialize `res` with:

```julia
res = zeros(size(a))

```

or

```julia
res = fill(0.0, size(a))

```

or even more extremely by:

```julia
res = zeros(promote_type(Base.return_types(function_of, (eltype(b),))...), size(a))

```

On a different note, the issue here was the silent instability of `func(::Float64)`. Maybe some mechanism which would warn against instabilities is appropriate out-of-the-box (without `@code_warntype`ing things).

---

<div class="post-metadata">

**Author:** ![GunnarFarneback](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gunnarfarneback/32/1827_2.png) [@GunnarFarneback](https://discourse.julialang.org/u/GunnarFarneback)\
**Post date:** [December 6, 2023, 8:16am UTC](https://discourse.julialang.org/t/zero-a-real/107175/24 "2023-12-06T08:16:42Z")

</div>

> [@ryofurue](#):
>
> `func(r) = (r == 0) ? 0 : somefunction(r)/r`

I might be stating the obvious, but the easiest improvement of this is

```julia
func(r) = (r == 0) ? r : somefunction(r)/r

```

---

<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:** [December 6, 2023, 12:29pm UTC](https://discourse.julialang.org/t/zero-a-real/107175/25 "2023-12-06T12:29:20Z")

</div>

> [@ryofurue](#):
>
> The rest of your discussion (thanks!) indicates that this isn’t a simple problem.

I hope I didn’t make it too complex. It can be as simple or complex as you want. I still maintain that Julia is the simplest language to get code right (for science at least; Clojure has good properties that most Julia programmers to not emulate, they could kill performance).

It’s hard in all languages to get the most speed, including in Julia, and type instability is NOT a bug per se, while can be considered a performance bug, even lowering it to under Python’s so I find it very important that Julia’s defaults are good, e.g. in this case, or easy to “fix” type instability and debug/track down. How did you find it, were tools good enough for that?

My emphasis was wrong with _your_ code, sorry about that, I was agreeing with you! That the type stability was there, but also considering a possible “usability bug” in Julia.

Now to make this even more complex. You opened quite a can of worms, and I thank you for opening this interesting thread. The division trick I knew of is maybe the most obscure Julia trick I know of.

> [@greatpet](#):
>
> func(r) = r == zero(r) ? zero(r) : r/3

Even I had to reread stuff, including mine, I was thinking zero(r) that’s what this is for, but I forgot the integer (and Rational) type-instability (I think stable for all other (float) types). I thought actually I would get away with 0 (but not 0.0):

```julia
func(r) = r == 0 ? zero(r) : r/3

@code_native func(1.0) # it's actually slightly larger (still type-stable I think), because of cast I thought would be optimized away.

func(r) = r == Bool(0) ? zero(r) : r/3 # this seems as good but back into obscurity.

```

Now I realize this is only an MWE, and the check not needed, the more interesting case is 1/r or even a/b:

```julia
func(r) = r/3 # simplest version, but you can absolutely not do r/3.0, if you care about rationals (or Float32 or lower).

```

> [@mikmoore](#):
>
> ```julia
> func(r) = iszero(r) ? zero(r)/1 : r/3
> func(r) = iszero(r) ? zero(r/1) : r/3 # alternative, but may behave slightly worse in some settings
> 
> ```

How do you extend that type-stability /1 trick to a/b? Note, a/b does NOT guarantee Float64 result, it.s. e.g. Float32 if both are, but you will get the larger type of the two (a question when float and e.g. Dec64 or Posit), or `Rational`s when applies, then the larger type of the two, and I don’t want to go there if num and dem are not the same type (not possible in Julia’s type, but possible in theory, I’ve been thinking of making my own (vectorized) rational type, and that’s one thing I’m considering…).

You want and trust that the /1 goes away in optimization, and it seems to, i.e. this sufficient:

```julia
func(a, b) = iszero(a) ? zero(a)/one(b) : a/b

@code_native func(1.0, 1) # only a screen-full, still much better than 3 for div(1.0, 1)

func2(a, b) = iszero(a) ? zero(a)/one(b) : div(a, b)

@code_native func2(1.0, 1) # is 5 screen-fulls of assembly...

```

At the assembly level you get a floating-point exception on most CPUs if you divide by zero (I don’t know of any that do not for floating-point).

First for integer divide:

```julia
@code_native div(1, 0) # I do not just get the slow idiv, but 20+-instruction overhead, for ijl_throw

```

The div-by-0 avoidance above was very costly. Some CPUs define idiv equivalent to return 0 for it. x86 does not, it has an interrupt, and I suppose it crashes your code, note that interrupt (“exception”) isn’t the same as a Julia exception, but can it be caught and handled by Julia? I.e. turn it into a Julia exception? Doing what Julia does natively, adding it’s own check, to prevent the interrupt ever happening, might be better than the user code doing it. And then catching that Julia exception and checking after the fact.

For a float div, you get a +/- Inf (or Inf32 etc.), but be careful or NaN for 0/0, so do not check for only one case after the fact for floting point. You CAN check for all cases with isfinite(0/0) and substitute your 0.0 (of right type…) then. But note, say this was exp (or part of your expression), and you can expect Inf, then do not substitute blindly. Division has high latency, so you may want to do it first, not a check first, (unpredictable) branches are also costly on top of that. If division-by-zero is likely rare, it might be worth it to check after.

You see I managed to made it even more complex, than just about type-stability…

> [@GunnarFarneback](#):
>
> the easiest improvement of this is
> 
> `func(r) = (r == 0) ? r : somefunction(r)/r`

If that somefunction is sin, i.e. you’re trying to implement sinc, then, intentionally showing the wrong version:

```julia
my_naive_sinc(r) = (r == 0) ? one(r) : sin(r)/r # sinc in base is the other definition

```

In such an example you can’t simply return r, and be careful not to return r + 1, either. For type stability you might think r works if `r + one(r)`, and then your back to just one(r), so rather useless, but neither that is type-stable!

That’s even though I see one used in Julia Base:

```julia
_sinc(x::Number) = iszero(x) ? one(x) : isinf_real(x) ? zero(x) : sinpi(x)/(pi*x)

```

Note there the integer case is handled separately. For my one-liner it needs to be:

```julia
my_naive_sinc(r) = (r == zero(r)) ? one(r)/1 : sin(r)/r # sinc in base is the other definition

```

So the lesson is avoid literal constants for type stability, but sadly, seeming `one` function (also `zero` I guess) is NOT a guarantee for success. It most often is enough though… And when it does seem to apply to have constants, e.g. for E=mc^2 that’s a separate (overflow-causing) issue.

The good thing is that perfect is the enemy of the good. Try to be type-stable, even if you only do it for floats, then it might be enough for you. In you non-package code you don’t even need to be fully generic, or even in part, just work with e.g. Float64. But in packages it’s best to be fully generic, if you fail you’re just one bug report away from that. You still don’t get incorrect results. The power ^ issue is an exception, one I’ve complained about and want to fix, get Float64 always… make it harder to opt into integer result.

[https://www.felixcloutier.com/x86/fdiv:fdivp:fidiv](https://www.felixcloutier.com/x86/fdiv:fdivp:fidiv)

[https://groups.google.com/g/llvm-dev/c/1FOyTcEJ3FI](https://groups.google.com/g/llvm-dev/c/1FOyTcEJ3FI)

> Per C and C++, integer division by 0 is undefined. That means, if it happens, the compiler is free to do whatever it wants. It is perfectly legal for LLVM to define r to be, say, 42 in this code; it is not required to preserve the fact that the idiv instruction on x86 andx86-64 will trap.

Note, while those languages are standardized, and don’t handle in the standard (I think most compiler implementations do something sensible), and Julia is NOT standardized, it’s till guarantees throwing its Julia exception, for integers only, otherwise following float-standard (maybe it should say why?):

```julia
julia> div(0,0)
ERROR: DivideError: integer division error

```

[https://developer.arm.com/documentation/ddi0406/c/Application-Level-Architecture/The-Instruction-Sets/Data-processing-instructions/Divide-instructions](https://developer.arm.com/documentation/ddi0406/c/Application-Level-Architecture/The-Instruction-Sets/Data-processing-instructions/Divide-instructions)

> - […] The Virtualization Extensions introduce the requirement for an ARMv7-A implementation to include `SDIV` and `UDIV`.
> - The ARMv7-M profile also includes the `SDIV` and `UDIV` instructions.
> 
> In the ARMv7-R profile, the [_SCTLR_](https://developer.arm.com/documentation/ddi0406/c/System-Level-Architecture/System-Control-Registers-in-a-PMSA-implementation/PMSA-System-control-registers-descriptions--in-register-order/SCTLR--System-Control-Register--PMSA?lang=en).DZ bit enables divide by zero fault detection:
> 
> [_SCTLR_](https://developer.arm.com/documentation/ddi0406/c/System-Level-Architecture/System-Control-Registers-in-a-PMSA-implementation/PMSA-System-control-registers-descriptions--in-register-order/SCTLR--System-Control-Register--PMSA?lang=en).DZ == 0
> 
> Divide-by-zero returns a zero result.
> 
> [_SCTLR_](https://developer.arm.com/documentation/ddi0406/c/System-Level-Architecture/System-Control-Registers-in-a-PMSA-implementation/PMSA-System-control-registers-descriptions--in-register-order/SCTLR--System-Control-Register--PMSA?lang=en).DZ == 1
> 
> `SDIV` and `UDIV` generate an Undefined Instruction exception on a divide-by-zero.

Julia supports ARMv7-A not ARMv7-R profile I think, but I’m just showing an example where you can get 0 out. I don’t know what the default flag is (for ARMv7-A), likely “divide by zero fault detection” enabled. I would like to know the best way to get single-instruction divide in machine code, and no Julia boilerplate, also for x86:

[https://pdos.csail.mit.edu/6.828/2008/readings/i386/IDIV.htm](https://pdos.csail.mit.edu/6.828/2008/readings/i386/IDIV.htm)

> Interrupt 0 if the quotient is too large to fit in the designated register (AL or AX), or if the divisor is 0

[Previous page](https://discourse.julialang.org/t/zero-a-real/107175.md?page=1)
