zig icon indicating copy to clipboard operation
zig copied to clipboard

Proposal: rename @fabs to @abs and accept integers and vectors of integers too

Open wooster0 opened this issue 1 year ago • 0 comments

This proposal is to merge std.math.absCast, std.math.absInt, and @fabs that currently only accepts floats and vectors of floats into an @abs and make that @abs additionally accept integers too as well as vectors of integers.

This new @abs converts and returns an unsigned integer if the argument is a signed integer. Same for vectors.

Status quo: @fabs, std.math.absCast, or std.math.absInt depending on your specific case.

  • absCast accepts signed or unsigned and always returns an unsigned integer so if the input is signed, it converts to unsigned.
  • absInt only takes a signed integer and returns a signed integer.

These are clunky and it takes a while to understand their differences.

With @abs, however, we always return an unsigned integer or a vector of unsigned integers if an integer or a vector of integers was given and the reason is that, generally, the user is perfectly fine with an unsigned integer type: when I grep the Zig codebase for absInt and look how absInt is used in those specific cases, there are actually zero legitimate real-world uses of absInt (at least in the Zig codebase). If you look for those absInt occurrences yourself you'll find that it's used either in tests or to implement some obscure C function (__builtin_abs).

Compare that to the 13 real-world uses of absCast that I found in the Zig codebase. So, you really just want @fabs or absCast.

So, new status quo: if you need a signed integer, just convert it yourself.

The advantage of combining all three into one is that you don't have to be confused about why we don't have std.math.abs or @abs. You no longer have to think about which one to use.

This was originally brought up by @jacobly0 here: https://github.com/ziglang/zig/pull/15879#discussion_r1220561951

Performance

There is actually also a performance benefit to be had here. As @jacobly0 pointed out to me, x86 actually has instructions for vectors of integers.

Currently, none of the 3 options can really take advantage of that in such a way those hardware instructions are emitted for sure. With an @abs builtin we can do that. absInt accepts vectors and uses vector builtins but still we have to rely on the optimizer there.

Finally, this should allow the backends to emit better code for regular integers too. For example in LLVM we don't seem to be using llvm.abs.*.

wooster0 avatar Jun 14 '23 01:06 wooster0