Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sat-arithmetic: add operator support #9679

Merged
merged 17 commits into from
Sep 29, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions doc/docgen.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1058,15 +1058,21 @@ fn tokenizeAndPrintRaw(
.plus_equal,
.plus_percent,
.plus_percent_equal,
.plus_pipe,
.plus_pipe_equal,
.minus,
.minus_equal,
.minus_percent,
.minus_percent_equal,
.minus_pipe,
.minus_pipe_equal,
.asterisk,
.asterisk_equal,
.asterisk_asterisk,
.asterisk_percent,
.asterisk_percent_equal,
.asterisk_pipe,
.asterisk_pipe_equal,
.arrow,
.colon,
.slash,
Expand All @@ -1079,6 +1085,8 @@ fn tokenizeAndPrintRaw(
.angle_bracket_left_equal,
.angle_bracket_angle_bracket_left,
.angle_bracket_angle_bracket_left_equal,
.angle_bracket_angle_bracket_left_pipe,
.angle_bracket_angle_bracket_left_pipe_equal,
.angle_bracket_right,
.angle_bracket_right_equal,
.angle_bracket_angle_bracket_right,
Expand Down
158 changes: 95 additions & 63 deletions doc/langref.html.in
Original file line number Diff line number Diff line change
Expand Up @@ -1244,8 +1244,9 @@ fn divide(a: i32, b: i32) i32 {
</p>
<p>
Operators such as {#syntax#}+{#endsyntax#} and {#syntax#}-{#endsyntax#} cause undefined behavior on
integer overflow. Also available are operations such as {#syntax#}+%{#endsyntax#} and
{#syntax#}-%{#endsyntax#} which are defined to have wrapping arithmetic on all targets.
integer overflow. Alternative operators are provided for wrapping and saturating arithmetic on all targets.
{#syntax#}+%{#endsyntax#} and {#syntax#}-%{#endsyntax#} perform wrapping arithmetic
while {#syntax#}+|{#endsyntax#} and {#syntax#}-|{#endsyntax#} perform saturating arithmetic.
</p>
<p>
Zig supports arbitrary bit-width integers, referenced by using
Expand Down Expand Up @@ -1395,6 +1396,23 @@ a +%= b{#endsyntax#}</pre></th>
<pre>{#syntax#}@as(u32, std.math.maxInt(u32)) +% 1 == 0{#endsyntax#}</pre>
</td>
</tr>
<tr>
<th scope="row"><pre>{#syntax#}a +| b
a +|= b{#endsyntax#}</pre></th>
<td>
<ul>
<li>{#link|Integers#}</li>
</ul>
</td>
<td>Saturating Addition.
<ul>
<li>Invokes {#link|Peer Type Resolution#} for the operands.</li>
</ul>
</td>
<td>
<pre>{#syntax#}@as(u32, std.math.maxInt(u32)) +| 1 == @as(u32, std.math.maxInt(u32)){#endsyntax#}</pre>
</td>
</tr>
<tr>
<th scope="row"><pre>{#syntax#}a - b
a -= b{#endsyntax#}</pre></th>
Expand Down Expand Up @@ -1434,6 +1452,23 @@ a -%= b{#endsyntax#}</pre></th>
<pre>{#syntax#}@as(u32, 0) -% 1 == std.math.maxInt(u32){#endsyntax#}</pre>
</td>
</tr>
<tr>
<th scope="row"><pre>{#syntax#}a -| b
a -|= b{#endsyntax#}</pre></th>
<td>
<ul>
<li>{#link|Integers#}</li>
</ul>
</td>
<td>Saturating Subtraction.
<ul>
<li>Invokes {#link|Peer Type Resolution#} for the operands.</li>
</ul>
</td>
<td>
<pre>{#syntax#}@as(u32, 0) -| 1 == 0{#endsyntax#}</pre>
</td>
</tr>
<tr>
<th scope="row"><pre>{#syntax#}-a{#endsyntax#}</pre></th>
<td>
Expand Down Expand Up @@ -1508,6 +1543,23 @@ a *%= b{#endsyntax#}</pre></th>
<pre>{#syntax#}@as(u8, 200) *% 2 == 144{#endsyntax#}</pre>
</td>
</tr>
<tr>
<th scope="row"><pre>{#syntax#}a *| b
a *|= b{#endsyntax#}</pre></th>
<td>
<ul>
<li>{#link|Integers#}</li>
</ul>
</td>
<td>Saturating Multiplication.
<ul>
<li>Invokes {#link|Peer Type Resolution#} for the operands.</li>
</ul>
</td>
<td>
<pre>{#syntax#}@as(u8, 200) *| 2 == 255{#endsyntax#}</pre>
</td>
</tr>
<tr>
<th scope="row"><pre>{#syntax#}a / b
a /= b{#endsyntax#}</pre></th>
Expand Down Expand Up @@ -1577,6 +1629,24 @@ a <<= b{#endsyntax#}</pre></th>
<pre>{#syntax#}1 << 8 == 256{#endsyntax#}</pre>
</td>
</tr>
<tr>
<th scope="row"><pre>{#syntax#}a <<| b
a <<|= b{#endsyntax#}</pre></th>
<td>
<ul>
<li>{#link|Integers#}</li>
</ul>
</td>
<td>Saturating Bit Shift Left.
<ul>
<li>See also {#link|@shlExact#}.</li>
<li>See also {#link|@shlWithOverflow#}.</li>
</ul>
</td>
<td>
<pre>{#syntax#}@as(u8, 1) <<| 8 == 255{#endsyntax#}</pre>
</td>
</tr>
<tr>
<th scope="row"><pre>{#syntax#}a >> b
a >>= b{#endsyntax#}</pre></th>
Expand Down Expand Up @@ -1968,14 +2038,14 @@ const B = error{Two};
a!b
x{}
!x -x -%x ~x &x ?x
* / % ** *% ||
+ - ++ +% -%
<< >>
* / % ** *% *| ||
+ - ++ +% -% +| -|
<< >> <<|
& ^ | orelse catch
== != < > <= >=
and
or
= *= /= %= += -= <<= >>= &= ^= |={#endsyntax#}</pre>
= *= *%= *|= /= %= += +%= +|= -= -%= -|= <<= <<|= >>= &= ^= |={#endsyntax#}</pre>
{#header_close#}
{#header_close#}
{#header_open|Arrays#}
Expand Down Expand Up @@ -7162,16 +7232,6 @@ fn readFile(allocator: *Allocator, filename: []const u8) ![]u8 {
If no overflow or underflow occurs, returns {#syntax#}false{#endsyntax#}.
</p>
{#header_close#}
{#header_open|@addWithSaturation#}
<pre>{#syntax#}@addWithSaturation(a: T, b: T) T{#endsyntax#}</pre>
<p>
Returns {#syntax#}a + b{#endsyntax#}. The result will be clamped between the type maximum and minimum.
</p>
<p>
Once <a href="https://github.com/ziglang/zig/issues/1284">Saturating arithmetic</a>.
is completed, the syntax {#syntax#}a +| b{#endsyntax#} will be equivalent to calling {#syntax#}@addWithSaturation(a, b){#endsyntax#}.
</p>
{#header_close#}
{#header_open|@alignCast#}
<pre>{#syntax#}@alignCast(comptime alignment: u29, ptr: anytype) anytype{#endsyntax#}</pre>
<p>
Expand Down Expand Up @@ -8293,22 +8353,6 @@ test "@wasmMemoryGrow" {
</p>
{#header_close#}

{#header_open|@mulWithSaturation#}
<pre>{#syntax#}@mulWithSaturation(a: T, b: T) T{#endsyntax#}</pre>
<p>
Returns {#syntax#}a * b{#endsyntax#}. The result will be clamped between the type maximum and minimum.
</p>
<p>
Once <a href="https://github.com/ziglang/zig/issues/1284">Saturating arithmetic</a>.
is completed, the syntax {#syntax#}a *| b{#endsyntax#} will be equivalent to calling {#syntax#}@mulWithSaturation(a, b){#endsyntax#}.
</p>
<p>
NOTE: Currently there is a bug in the llvm.smul.fix.sat intrinsic which affects {#syntax#}@mulWithSaturation{#endsyntax#} of signed integers.
This may result in an incorrect sign bit when there is overflow. This will be fixed in zig's 0.9.0 release.
Check <a href="https://github.com/ziglang/zig/issues/9643">this issue</a> for more information.
</p>
{#header_close#}

{#header_open|@panic#}
<pre>{#syntax#}@panic(message: []const u8) noreturn{#endsyntax#}</pre>
<p>
Expand Down Expand Up @@ -8526,14 +8570,16 @@ test "@setRuntimeSafety" {
{#header_open|@shlExact#}
<pre>{#syntax#}@shlExact(value: T, shift_amt: Log2T) T{#endsyntax#}</pre>
<p>
Performs the left shift operation ({#syntax#}<<{#endsyntax#}). Caller guarantees
that the shift will not shift any 1 bits out.
Performs the left shift operation ({#syntax#}<<{#endsyntax#}).
For unsigned integers, the result is {#link|undefined#} if any 1 bits
are shifted out. For signed integers, the result is {#link|undefined#} if
any bits that disagree with the resultant sign bit are shifted out.
</p>
<p>
The type of {#syntax#}shift_amt{#endsyntax#} is an unsigned integer with {#syntax#}log2(T.bit_count){#endsyntax#} bits.
This is because {#syntax#}shift_amt >= T.bit_count{#endsyntax#} is undefined behavior.
</p>
{#see_also|@shrExact|@shlWithOverflow|@shlWithSaturation#}
{#see_also|@shrExact|@shlWithOverflow#}
{#header_close#}

{#header_open|@shlWithOverflow#}
Expand All @@ -8547,24 +8593,9 @@ test "@setRuntimeSafety" {
The type of {#syntax#}shift_amt{#endsyntax#} is an unsigned integer with {#syntax#}log2(T.bit_count){#endsyntax#} bits.
This is because {#syntax#}shift_amt >= T.bit_count{#endsyntax#} is undefined behavior.
</p>
{#see_also|@shlExact|@shrExact|@shlWithSaturation#}
{#see_also|@shlExact|@shrExact#}
{#header_close#}

{#header_open|@shlWithSaturation#}
<pre>{#syntax#}@shlWithSaturation(a: T, shift_amt: T) T{#endsyntax#}</pre>
<p>
Returns {#syntax#}a << b{#endsyntax#}. The result will be clamped between type minimum and maximum.
</p>
<p>
Once <a href="https://github.com/ziglang/zig/issues/1284">Saturating arithmetic</a>.
is completed, the syntax {#syntax#}a <<| b{#endsyntax#} will be equivalent to calling {#syntax#}@shlWithSaturation(a, b){#endsyntax#}.
</p>
<p>
Unlike other @shl builtins, shift_amt doesn't need to be a Log2T as saturated overshifting is well defined.
</p>
{#see_also|@shlExact|@shrExact|@shlWithOverflow#}
{#header_close#}

{#header_open|@shrExact#}
<pre>{#syntax#}@shrExact(value: T, shift_amt: Log2T) T{#endsyntax#}</pre>
<p>
Expand All @@ -8575,7 +8606,7 @@ test "@setRuntimeSafety" {
The type of {#syntax#}shift_amt{#endsyntax#} is an unsigned integer with {#syntax#}log2(T.bit_count){#endsyntax#} bits.
This is because {#syntax#}shift_amt >= T.bit_count{#endsyntax#} is undefined behavior.
</p>
{#see_also|@shlExact|@shlWithOverflow|@shlWithSaturation#}
{#see_also|@shlExact|@shlWithOverflow#}
{#header_close#}

{#header_open|@shuffle#}
Expand Down Expand Up @@ -8875,17 +8906,6 @@ fn doTheTest() !void {
</p>
{#header_close#}

{#header_open|@subWithSaturation#}
<pre>{#syntax#}@subWithSaturation(a: T, b: T) T{#endsyntax#}</pre>
<p>
Returns {#syntax#}a - b{#endsyntax#}. The result will be clamped between the type maximum and minimum.
</p>
<p>
Once <a href="https://github.com/ziglang/zig/issues/1284">Saturating arithmetic</a>.
is completed, the syntax {#syntax#}a -| b{#endsyntax#} will be equivalent to calling {#syntax#}@subWithSaturation(a, b){#endsyntax#}.
</p>
{#header_close#}

{#header_open|@tagName#}
<pre>{#syntax#}@tagName(value: anytype) [:0]const u8{#endsyntax#}</pre>
<p>
Expand Down Expand Up @@ -11839,6 +11859,7 @@ AssignOp
/ PLUSEQUAL
/ MINUSEQUAL
/ LARROW2EQUAL
/ LARROW2PIPEEQUAL
/ RARROW2EQUAL
/ AMPERSANDEQUAL
/ CARETEQUAL
Expand Down Expand Up @@ -11873,6 +11894,8 @@ AdditionOp
/ PLUS2
/ PLUSPERCENT
/ MINUSPERCENT
/ PLUSPIPE
/ MINUSPIPE

MultiplyOp
&lt;- PIPE2
Expand All @@ -11881,6 +11904,7 @@ MultiplyOp
/ PERCENT
/ ASTERISK2
/ ASTERISKPERCENT
/ ASTERISKPIPE

PrefixOp
&lt;- EXCLAMATIONMARK
Expand Down Expand Up @@ -12044,6 +12068,8 @@ ASTERISK2 &lt;- '**' skip
ASTERISKEQUAL &lt;- '*=' skip
ASTERISKPERCENT &lt;- '*%' ![=] skip
ASTERISKPERCENTEQUAL &lt;- '*%=' skip
ASTERISKPIPE &lt;- '*|' ![=] skip
ASTERISKPIPEEQUAL &lt;- '*|=' skip
CARET &lt;- '^' ![=] skip
CARETEQUAL &lt;- '^=' skip
COLON &lt;- ':' skip
Expand All @@ -12060,6 +12086,8 @@ EXCLAMATIONMARK &lt;- '!' ![=] skip
EXCLAMATIONMARKEQUAL &lt;- '!=' skip
LARROW &lt;- '&lt;' ![&lt;=] skip
LARROW2 &lt;- '&lt;&lt;' ![=] skip
LARROW2PIPE &lt;- '&lt;&lt;|' ![=] skip
LARROW2PIPEEQUAL &lt;- '&lt;&lt;|=' ![=] skip
LARROW2EQUAL &lt;- '&lt;&lt;=' skip
LARROWEQUAL &lt;- '&lt;=' skip
LBRACE &lt;- '{' skip
Expand All @@ -12069,6 +12097,8 @@ MINUS &lt;- '-' ![%=&gt;] skip
MINUSEQUAL &lt;- '-=' skip
MINUSPERCENT &lt;- '-%' ![=] skip
MINUSPERCENTEQUAL &lt;- '-%=' skip
MINUSPIPE &lt;- '-|' ![=] skip
MINUSPIPEEQUAL &lt;- '-|=' skip
MINUSRARROW &lt;- '-&gt;' skip
PERCENT &lt;- '%' ![=] skip
PERCENTEQUAL &lt;- '%=' skip
Expand All @@ -12080,6 +12110,8 @@ PLUS2 &lt;- '++' skip
PLUSEQUAL &lt;- '+=' skip
PLUSPERCENT &lt;- '+%' ![=] skip
PLUSPERCENTEQUAL &lt;- '+%=' skip
PLUSPIPE &lt;- '+|' ![=] skip
PLUSPIPEEQUAL &lt;- '+|=' skip
LETTERC &lt;- 'c' skip
QUESTIONMARK &lt;- '?' skip
RARROW &lt;- '&gt;' ![&gt;=] skip
Expand Down
Loading