Skip to content

Commit

Permalink
Merge pull request #9679 from travisstaloch/sat-arith-operators
Browse files Browse the repository at this point in the history
sat-arithmetic: add operator support
  • Loading branch information
andrewrk authored Sep 29, 2021
2 parents 79bc589 + 5467582 commit cf90cb7
Show file tree
Hide file tree
Showing 31 changed files with 1,319 additions and 473 deletions.
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

0 comments on commit cf90cb7

Please sign in to comment.