<p>In many programming languages, there is a ternary operator such as <code>X ? Y : Z</code> or <code>Y if X else Z</code>. This can be used as an <code>if</code> expression.</p>
<p>However, I was wondering what other ternary operators are possible and useful. I was looking for operations that come up frequently enough to warrant their own syntax or keywords that take in three operands.</p>

<syntax><language-design><operators>
Ternary operators other than ?:
CC BY-SA 4.0
2023-10-03T03:24:43.620Z
I guess this assumes that your language makes a syntactic distinction between "operators" and other arbitrary functions.
Nate Eldredge
<p><a href="https://ioke.org/" rel="noreferrer">Ioke</a> and <a href="https://seph-lang.org/" rel="noreferrer">Seph</a> have something called <a href="https://ioke.org/dok/latest/kinds/Message/OperatorTable.html#C00904" rel="noreferrer"><em>trinary operators</em></a>.</p>
<p><em>Trinary</em> operators in Ioke and Seph are operators that are <em>written as binary operators</em> but <em>executed as ternary operators</em>. In particular, <a href="https://ioke.org/dok/latest/kinds/DefaultBehavior/Assignment.html#C0044" rel="noreferrer">the default behavior of the trinary operators (like all operators in Ioke and Seph, they can be overridden) is <em>assignment</em></a>.</p>
<p>One of the fundamental goals of Ioke and Seph is to have a small and simple kernel and implement as much as possible through message sending. Even assignment is implemented as a message send.</p>
<p>When you write</p>
<pre class="lang-none prettyprint-override"><code>a = b
</code></pre>
<p>I.e. the <em>binary infix assignment</em> operator, that is actually syntactic sugar for</p>
<pre class="lang-none prettyprint-override"><code>=(a, b)
</code></pre>
<p>I.e. <a href="https://ioke.org/dok/latest/kinds/Base.html#C007" rel="noreferrer">sending the message <code>=</code></a> with the <em>un-evaluated argument</em> <code>a</code> (denoting the name of the cell you want to assign to) and the <em>evaluated argument</em> <code>b</code> (the value you want to assign) to the <em>current ground</em> (which is somewhat of a hybrid of a Smalltalk-style <code>self</code> or <code>this</code> and a Scheme-style lexical closure context). So, when you <em>write</em> the <em>binary</em> assignment operator with the variable on the left-hand side and the value on the right-hand side, you are actually executing a <em>ternary</em> operator with the first operand being the current context, the second argument being the name of the variable, and the third being the value.</p>

CC BY-SA 4.0
2023-07-01T12:17:24.143Z
2023-07-01T12:17:24.143Z
Jörg W Mittag
CC BY-SA 4.0
2023-07-01T14:55:26.237Z
That's... pretty wild, although vaguely reminiscent of some ideas I've had myself.
Karl Knechtel
<p>While I'm unaware of any languages that actually work this way, it could conceivably be useful to treat repeated applications of a binary operator as if they were a ternary (really, n-ary) operator.</p>
<p>For example, suppose the grammar recognizes &quot;term&quot; mathematical expressions formed by <code>+</code> or <code>-</code>; it could be useful to transform e.g. <code>a + b - c</code> into <code>a.sum_with(b, -c)</code> at compile time<sup>1</sup>. This way, for example, container types could offer an optimized implementation for concatenation, without needing to hard-code that into the runtime.</p>
<p><sub><sup>1</sup> Here, the method name <code>sum_with</code> is hard-coded as being specially for implementing this arithmetic; maybe it's spelled <code>sum</code>, or <code>__sum__</code>, or <code>operator+</code>, etc. Similarly, maybe the arguments would be passed in a new container object, rather than variadically. None of these implementation details matter to the underlying idea.</sub></p>

CC BY-SA 4.0
2023-07-01T15:03:58.307Z
2023-07-01T15:03:58.307Z
Karl Knechtel
CC BY-SA 4.0
2023-07-01T15:04:17.543Z
Defining the semantics of unary negation for containers is left as an exercise, of course. ;)
Karl Knechtel
CC BY-SA 4.0
2023-07-03T02:46:30.410Z
Mathematica works like this. `a+b+c` is transformed into `Plus[a,b,c]`.
alephalpha
<p>Many graphics and control applications could benefit from a bitwise variation of the <code>? :</code> operator, and a compound-assignment variation, though the most natural syntax for assignment operator would put the operands in a different order from <code>? :</code> (the non-assignment form could be patterned after <code>? :</code> as shown below, or after the assignment form).</p>
<pre><code>unsigned cookieCutter(unsigned mask, unsigned op0, unsigned op1)
{
  return (((op0 ^ op1) &amp; mask) ^ op1);
}

// For non-atomic destination
unsigned cookieCutterAssign(unsigned *dest, unsigned mask, unsigned newBits)
{
  *dest = (((newBits ^ *dest) &amp; mask) ^ *dest);
}

// For atomic destination
unsigned cookieCutterAssign(unsigned *dest, unsigned mask, unsigned newBits)
{
  unsigned temp;
  do
  {
    temp = *dest;
  } while(!__compareAndSwap(dest, ((newBits ^ temp) &amp; mask) ^ temp, temp);
}
</code></pre>
<p>The need to use one of the values twice in the computation makes such constructs awkward to write using binary bitwise operators.</p>

CC BY-SA 4.0
2023-10-02T21:59:03.690Z
2023-10-02T21:59:03.690Z
supercat
<p>In SQL, as well as the <code>BETWEEN</code> operator already mentioned, I tend to regard the joins themselves as ternary operators.</p>
<p>A <code>LEFT JOIN ... ON</code> takes two table operands, plus a control expression.</p>

CC BY-SA 4.0
2023-10-03T07:42:26.363Z
2023-10-03T07:42:26.363Z
Steve
<p>In lower-level languages, the basic arithmetic and logical operators are often chosen to mirror the operations available as hardware CPU instructions.  This makes it particularly easy for a naive compiler to recognize when the corresponding instructions can be used.  For instance, on a machine with a read-modify-write add instruction, C's <code>+=</code> operator is valuable, because even a non-optimizing compiler can see that it should emit the RMW version.  Abstractly, <code>+=</code> is unnecessary because <code>x += y</code> is equivalent to <code>x = x + y</code>, but a non-optimizing compiler would likely emit three instructions (load, add, store) for the latter.</p>
<p>In that spirit, I thought I'd look through the ARM64 base instruction set for instructions with three or more input operands, as potential candidates for ternary operators in a language.  Here's a summary, with C-like syntax to describe the operation.  <code>x,y,z,w</code> denote register inputs (i.e. run-time values), <code>a,b,c,d</code> are immediates (compile-time constants).</p>
<ul>
<li><p>Shifted arithmetic and bitwise operations.  Most of the basic ALU instructions have an option to run one of the inputs through a barrel shifter first, so we have a single instruction that can compute <code>x + (y &lt;&lt; a)</code>.  The <code>&lt;&lt;</code> can be replaced with right-shift (logical or arithmetic) or with rotate.  This option is available for the operations <code>+ - &amp; | ^</code> as well as inverted bitwise operations <code>&amp;~ |~ ^~</code> (e.g. the bit-clear instruction <code>BIC</code> computes <code>x &amp; ~(y &lt;&lt; a)</code>)</p>
</li>
<li><p>Bitfield move <code>BFM</code>.  This is actually a quaternary operator, which replaces bits <code>a</code> through <code>b</code> of the value <code>x</code> with the low-order bits of <code>y</code>, or vice versa.</p>
</li>
<li><p>Conditional select <code>CSEL</code>.  Here the flags register is an implicit input, so it's effectively the familiar conditional operator <code>x ? y : z</code>.  One interesting wrinkle is that there are variants <code>CSINC</code>, <code>CSNEG</code>, <code>CSINV</code> which respectively do <code>x ? y : z+1</code>, <code>x ? y : -z</code>, and <code>x ? y : ~z</code>.</p>
</li>
<li><p>Conditional-compare <code>CCMP</code>.  This is kind of hard to describe in C terms, but roughly does something like <code>x ? (y &lt; z) : a</code>.  The constant input <code>a</code> looks redundant in C, but the point is that <code>a</code> may set a different condition code than <code>y &lt; z</code> would.</p>
</li>
<li><p>Add with carry <code>ADC</code>.  If we again think of the carry flag as an implicit input, then this does <code>x + y + z</code> where <code>z</code> can only be 0 or 1. There is also <code>SBC</code> which does <code>x - y - z</code>.</p>
</li>
<li><p>Multiply-add <code>MADD</code> and multiply-subtract <code>MSUB</code>.  These do <code>x + (y * z)</code> and <code>x - (y * z)</code>.  A fun fact is that ARM64 does not actually have a simple multiply instruction; the <code>MUL</code> mnemonic is an alias of <code>MADD</code> with <code>x</code> taken as the zero register <code>xzr</code> whose value is always zero.</p>
</li>
<li><p>Extract <code>EXTR</code>.  This is basically right-shift, but with a double-wide 128-bit input that spans two 64-bit registers.  So it doesn't really count for a higher-level language, which would just denote as <code>x &gt;&gt; a</code> where <code>x</code> was of a 128-bit type.</p>
</li>
<li><p>Store <code>STR</code> with base and index.  Does <code>x[y] = z</code>.  There is also store-pair which does <code>x[a]=y, x[a+1]=z</code>, but as with <code>EXTR</code> above, this is basically <code>x[a]=y</code> where <code>y</code> is 128 bits.</p>
</li>
<li><p>Test bit and conditional branch <code>TBNZ/TBZ</code>.  They do <code>if (x &amp; (1 &lt;&lt; a)) goto b;</code> and <code>if (!(x &amp; (1 &lt;&lt; a))) goto b;</code>  These wouldn't likely show up in a higher-level language, because the target of a branch is not usually an explicit expression; instead, it's determined by the block structure of the code.</p>
</li>
</ul>
<p>I didn't go through the floating-point and SIMD instruction sets carefully, but a couple worth mentioning are:</p>
<ul>
<li><p>floating point multiply-add <code>FMADD/FMSUB</code></p>
</li>
<li><p><code>BSL</code> which is supercat's &quot;cookie cutter&quot; operation, basically bitwise <code>?:</code>.</p>
</li>
<li><p>A variety of fancy bitwise operations for accelerating CRC / SHA / AES.</p>
</li>
</ul>

CC BY-SA 4.0
2023-10-03T04:40:55.470Z
2023-10-03T04:53:14.333Z
2023-10-03T04:53:14.333Z
Nate Eldredge
<p><a href="https://en.wikipedia.org/wiki/Ternary_operation#Computer_science" rel="noreferrer">Wikipedia</a> lists the following ones, which I let here operate on arguments <code>a</code>, <code>b</code> and <code>c</code>:</p>
<ul>
<li>The <a href="https://en.wikipedia.org/wiki/Multiply%E2%80%93accumulate_operation" rel="noreferrer">Multiply–accumulate operation</a>, which is commonly used in digital signal processing. In pseudo-code: <code>a += b * c</code></li>
<li>The 'between' operator, as used e.g. in <a href="https://learn.microsoft.com/en-us/sql/t-sql/language-elements/between-transact-sql?view=sql-server-ver16" rel="noreferrer">SQL</a>: <code>b &lt;= a &lt;= c</code></li>
<li>A range iterator with step size, <code>for (int i = a; i &lt; b; i += c)</code></li>
</ul>

CC BY-SA 4.0
2023-05-18T10:47:10.620Z
2023-05-18T10:47:10.620Z
Glorfindel
CC BY-SA 4.0
2023-10-03T20:34:53.317Z
It's hard to imagine a more compact syntax for the multiply-accumulate operation.
Barmar
CC BY-SA 4.0
2023-05-18T10:52:14.163Z
I guess in python the full form of the slice operator `a[b:c:d]` is basically one quadranary operator
mousetail 'he-him'
CC BY-SA 4.0
2023-07-01T14:51:19.830Z
@mousetail No, I wouldn't say so. `b:c:d` is a separate syntax which creates a `slice` object, and that object gets passed to `a`'s `__getitem__` method. (In earlier versions, `b`, `c`, `d` could become separate arguments for a method.) So the `[]` is a separate operator that's part of a compound expression. This is also evident from the actual parse grammar. Similarly, the only reason for treating multiply-accumulate as a single operation is because there is hardware support for doing so.
Karl Knechtel
CC BY-SA 4.0
2023-07-01T14:59:03.923Z
@KarlKnechtel You can't create a slice using this syntax in any other situation though
mousetail 'he-him'
CC BY-SA 4.0
2023-07-01T15:07:12.383Z
Hmm, well, there *is* that. :)
Karl Knechtel
<p>Any function of three arguments could, in principle, be made into an operator; but usually they are not operators, because few functions are so important that they need a special syntax. In specialised languages some operations might be important enough, e.g. perhaps &quot;lerp&quot; or &quot;clamp&quot; for graphics applications. Otherwise these operations can be provided as named functions in the standard library, and then not only do they not take up syntax space, but the compiler doesn't need to know how to implement them.</p>
<p>The conditional expression is a bit of a special case, because it does branching, so it can't be equivalently written as a function whose arguments are evaluated eagerly. Other operations which branch include the short-circuiting logical operators <code>and</code>/<code>&amp;&amp;</code> and <code>or</code>/<code>||</code>, but these are binary rather than ternary.</p>
<p>But perhaps there could be other branching ternary operators; a good place to look would be common standard library functions which accept a callback in order to avoid eager evaluation. Some suggestions:</p>
<ul>
<li>&quot;Get or default&quot; from a dictionary. If a normal indexed access gives a null value when the key is missing, then this can be written like <code>dictionary[key] ?? default_value</code> where <code>??</code> is a null-coalescing binary operator, but if a missing key raises an error instead then this wouldn't be an option, so a ternary operator could be useful.</li>
<li>&quot;Compute if not present&quot; in a dictionary, which likewise could be written like <code>dictionary[key] ??= default_value</code> with a null-coalescing assignment operator, but only if a missing key results in a null value rather than an error.</li>
</ul>
<p>Another one which occurs to me is a logical operator which checks whether at least two of three operands are true, sometimes called the <a href="https://en.wikipedia.org/wiki/Majority_function" rel="noreferrer">majority function</a>. As a function, <code>maj(a, b, c)</code> would evaluate <code>c</code> unnecessarily when both <code>a</code> and <code>b</code> are already true (or both already false), but there is no convenient way to write something equivalent using just the short-circuiting binary logical operators, so perhaps some languages would benefit from this being a ternary operator.</p>
<p>Finally, slicing a sequence like <code>a[b:c]</code> could be implemented as a ternary operator; some languages (e.g. Python) decompose this into an indexed access where the index is a &quot;slice&quot; object representing the range <code>b:c</code>, but if you don't want to create &quot;slices&quot; as first-class objects in your language then this could be a ternary operator instead.</p>

CC BY-SA 4.0
2023-05-18T11:21:40.367Z
2023-05-18T12:33:30.180Z
2023-05-18T12:33:30.180Z
kaya3
CC BY-SA 4.0
2023-07-01T12:19:55.077Z
Something which isn't obvious, but becomes clear when you think about it, is that *assignment* is actually a ternary operation, with the three operands being the scope, the cell, and the value. Ioke and Seph are two languages that execute assignment `a = b` as a message send to the current implicit receiver with two arguments: `=(a, b)`. So, it is written as a binary operator but executed as a ternary. (Arguments are passed un-evaluated and the method implementation can choose whether to evaluate them or inspect them raw, hence `a` does not raise an error.)
Jörg W Mittag
CC BY-SA 4.0
2023-10-02T21:43:40.243Z
Another useful operator, especially for graphics but also in some control algorithms, is `(((x ^ z) & y) ^ z` (but with `z` only evaluated once).  This is also very useful to have as an atomic pseudo-primitive (which would typically be built from Compare-and-swap, CompareExchange, or other lower-level primitives.)
supercat
CC BY-SA 4.0
2023-10-02T21:46:38.787Z
@supercat Sounds like that could be an answer.
kaya3
# Ternary operators other than ?:
Posted by: username_0 on 2023-05-18
In many programming languages, there is a ternary operator such as `X ? Y : Z` or `Y if X else Z`. This can be used as an `if` expression.

However, I was wondering what other ternary operators are possible and useful. I was looking for operations that come up frequently enough to warrant their own syntax or keywords that take in three operands.
**Tags:** syntax language-design operators
> **Comments:**
> **username_1**: I guess this assumes that your language makes a syntactic distinction between "operators" and other arbitrary functions.  
---
## 7 answers
### Answer by username_7 on 2023-05-18. Score: 14 | Accepted answer
[Wikipedia](https://en.wikipedia.org/wiki/Ternary_operation#Computer_science) lists the following ones, which I let here operate on arguments `a`, `b` and `c`:

* The [Multiply–accumulate operation](https://en.wikipedia.org/wiki/Multiply%E2%80%93accumulate_operation), which is commonly used in digital signal processing. In pseudo-code: `a += b * c`
* The 'between' operator, as used e.g. in [SQL](https://learn.microsoft.com/en-us/sql/t-sql/language-elements/between-transact-sql?view=sql-server-ver16): `b <= a <= c`
* A range iterator with step size, `for (int i = a; i < b; i += c)`
> **Comments:**
> **username_9** (2023-05-18): I guess in python the full form of the slice operator `a[b:c:d]` is basically one quadranary operator  
> **username_3** (2023-07-01): @mousetail No, I wouldn't say so. `b:c:d` is a separate syntax which creates a `slice` object, and that object gets passed to `a`'s `__getitem__` method. (In earlier versions, `b`, `c`, `d` could become separate arguments for a method.) So the `[]` is a separate operator that's part of a compound expression. This is also evident from the actual parse grammar. Similarly, the only reason for treating multiply-accumulate as a single operation is because there is hardware support for doing so.  
> **username_9** (2023-07-01): @KarlKnechtel You can't create a slice using this syntax in any other situation though  
> **username_3** (2023-07-01): Hmm, well, there *is* that. :)  
> **username_8** (2023-10-03): It's hard to imagine a more compact syntax for the multiply-accumulate operation.  
---
### Answer by username_10 on 2023-05-18. Score: 9
Any function of three arguments could, in principle, be made into an operator; but usually they are not operators, because few functions are so important that they need a special syntax. In specialised languages some operations might be important enough, e.g. perhaps "lerp" or "clamp" for graphics applications. Otherwise these operations can be provided as named functions in the standard library, and then not only do they not take up syntax space, but the compiler doesn't need to know how to implement them.

The conditional expression is a bit of a special case, because it does branching, so it can't be equivalently written as a function whose arguments are evaluated eagerly. Other operations which branch include the short-circuiting logical operators `and`/`&&` and `or`/`||`, but these are binary rather than ternary.

But perhaps there could be other branching ternary operators; a good place to look would be common standard library functions which accept a callback in order to avoid eager evaluation. Some suggestions:

* "Get or default" from a dictionary. If a normal indexed access gives a null value when the key is missing, then this can be written like `dictionary[key] ?? default_value` where `??` is a null-coalescing binary operator, but if a missing key raises an error instead then this wouldn't be an option, so a ternary operator could be useful.
* "Compute if not present" in a dictionary, which likewise could be written like `dictionary[key] ??= default_value` with a null-coalescing assignment operator, but only if a missing key results in a null value rather than an error.

Another one which occurs to me is a logical operator which checks whether at least two of three operands are true, sometimes called the [majority function](https://en.wikipedia.org/wiki/Majority_function). As a function, `maj(a, b, c)` would evaluate `c` unnecessarily when both `a` and `b` are already true (or both already false), but there is no convenient way to write something equivalent using just the short-circuiting binary logical operators, so perhaps some languages would benefit from this being a ternary operator.

Finally, slicing a sequence like `a[b:c]` could be implemented as a ternary operator; some languages (e.g. Python) decompose this into an indexed access where the index is a "slice" object representing the range `b:c`, but if you don't want to create "slices" as first-class objects in your language then this could be a ternary operator instead.
> **Comments:**
> **username_2** (2023-07-01): Something which isn't obvious, but becomes clear when you think about it, is that *assignment* is actually a ternary operation, with the three operands being the scope, the cell, and the value. Ioke and Seph are two languages that execute assignment `a = b` as a message send to the current implicit receiver with two arguments: `=(a, b)`. So, it is written as a binary operator but executed as a ternary. (Arguments are passed un-evaluated and the method implementation can choose whether to evaluate them or inspect them raw, hence `a` does not raise an error.)  
> **username_5** (2023-10-02): Another useful operator, especially for graphics but also in some control algorithms, is `(((x ^ z) & y) ^ z` (but with `z` only evaluated once).  This is also very useful to have as an atomic pseudo-primitive (which would typically be built from Compare-and-swap, CompareExchange, or other lower-level primitives.)  
> **username_10** (2023-10-02): @supercat Sounds like that could be an answer.  
---
### Answer by username_2 on 2023-07-01. Score: 5
Ioke and Seph have something called trinary operators.
Trinary operators in Ioke and Seph are operators that are written as binary operators but executed as ternary operators. In particular, the default behavior of the trinary operators (like all operators in Ioke and Seph, they can be overridden) is assignment.
One of the fundamental goals of Ioke and Seph is to have a small and simple kernel and implement as much as possible through message sending. Even assignment is implemented as a message send.
When you write
a = b

I.e. the binary infix assignment operator, that is actually syntactic sugar for
=(a, b)

I.e. sending the message = with the un-evaluated argument a (denoting the name of the cell you want to assign to) and the evaluated argument b (the value you want to assign) to the current ground (which is somewhat of a hybrid of a Smalltalk-style self or this and a Scheme-style lexical closure context). So, when you write the binary assignment operator with the variable on the left-hand side and the value on the right-hand side, you are actually executing a ternary operator with the first operand being the current context, the second argument being the name of the variable, and the third being the value.
> **Comments:**
> **username_3** (2023-07-01): That's... pretty wild, although vaguely reminiscent of some ideas I've had myself.  
---
### Answer by username_3 on 2023-07-01. Score: 5
While I'm unaware of any languages that actually work this way, it could conceivably be useful to treat repeated applications of a binary operator as if they were a ternary (really, n-ary) operator.

For example, suppose the grammar recognizes "term" mathematical expressions formed by `+` or `-`; it could be useful to transform e.g. `a + b - c` into `a.sum_with(b, -c)` at compile time1. This way, for example, container types could offer an optimized implementation for concatenation, without needing to hard-code that into the runtime.

1 Here, the method name `sum_with` is hard-coded as being specially for implementing this arithmetic; maybe it's spelled `sum`, or `__sum__`, or `operator+`, etc. Similarly, maybe the arguments would be passed in a new container object, rather than variadically. None of these implementation details matter to the underlying idea.
> **Comments:**
> **username_3** (2023-07-01): Defining the semantics of unary negation for containers is left as an exercise, of course. ;)  
> **username_4** (2023-07-03): Mathematica works like this. `a+b+c` is transformed into `Plus[a,b,c]`.  
---
### Answer by username_5 on 2023-10-02. Score: 2
Many graphics and control applications could benefit from a bitwise variation of the ? : operator, and a compound-assignment variation, though the most natural syntax for assignment operator would put the operands in a different order from ? : (the non-assignment form could be patterned after ? : as shown below, or after the assignment form).
unsigned cookieCutter(unsigned mask, unsigned op0, unsigned op1)
{
  return (((op0 ^ op1) & mask) ^ op1);
}

// For non-atomic destination
unsigned cookieCutterAssign(unsigned *dest, unsigned mask, unsigned newBits)
{
  *dest = (((newBits ^ *dest) & mask) ^ *dest);
}

// For atomic destination
unsigned cookieCutterAssign(unsigned *dest, unsigned mask, unsigned newBits)
{
  unsigned temp;
  do
  {
    temp = *dest;
  } while(!__compareAndSwap(dest, ((newBits ^ temp) & mask) ^ temp, temp);
}

The need to use one of the values twice in the computation makes such constructs awkward to write using binary bitwise operators.
---
### Answer by username_6 on 2023-10-03. Score: 1
In SQL, as well as the `BETWEEN` operator already mentioned, I tend to regard the joins themselves as ternary operators.

A `LEFT JOIN ... ON` takes two table operands, plus a control expression.
---
### Answer by username_1 on 2023-10-03. Score: 1
In lower-level languages, the basic arithmetic and logical operators are often chosen to mirror the operations available as hardware CPU instructions. This makes it particularly easy for a naive compiler to recognize when the corresponding instructions can be used. For instance, on a machine with a read-modify-write add instruction, C's `+=` operator is valuable, because even a non-optimizing compiler can see that it should emit the RMW version. Abstractly, `+=` is unnecessary because `x += y` is equivalent to `x = x + y`, but a non-optimizing compiler would likely emit three instructions (load, add, store) for the latter.

In that spirit, I thought I'd look through the ARM64 base instruction set for instructions with three or more input operands, as potential candidates for ternary operators in a language. Here's a summary, with C-like syntax to describe the operation. `x,y,z,w` denote register inputs (i.e. run-time values), `a,b,c,d` are immediates (compile-time constants).

* Shifted arithmetic and bitwise operations. Most of the basic ALU instructions have an option to run one of the inputs through a barrel shifter first, so we have a single instruction that can compute `x + (y << a)`. The `<<` can be replaced with right-shift (logical or arithmetic) or with rotate. This option is available for the operations `+ - & | ^` as well as inverted bitwise operations `&~ |~ ^~` (e.g. the bit-clear instruction `BIC` computes `x & ~(y << a)`)
* Bitfield move `BFM`. This is actually a quaternary operator, which replaces bits `a` through `b` of the value `x` with the low-order bits of `y`, or vice versa.
* Conditional select `CSEL`. Here the flags register is an implicit input, so it's effectively the familiar conditional operator `x ? y : z`. One interesting wrinkle is that there are variants `CSINC`, `CSNEG`, `CSINV` which respectively do `x ? y : z+1`, `x ? y : -z`, and `x ? y : ~z`.
* Conditional-compare `CCMP`. This is kind of hard to describe in C terms, but roughly does something like `x ? (y < z) : a`. The constant input `a` looks redundant in C, but the point is that `a` may set a different condition code than `y < z` would.
* Add with carry `ADC`. If we again think of the carry flag as an implicit input, then this does `x + y + z` where `z` can only be 0 or 1. There is also `SBC` which does `x - y - z`.
* Multiply-add `MADD` and multiply-subtract `MSUB`. These do `x + (y * z)` and `x - (y * z)`. A fun fact is that ARM64 does not actually have a simple multiply instruction; the `MUL` mnemonic is an alias of `MADD` with `x` taken as the zero register `xzr` whose value is always zero.
* Extract `EXTR`. This is basically right-shift, but with a double-wide 128-bit input that spans two 64-bit registers. So it doesn't really count for a higher-level language, which would just denote as `x >> a` where `x` was of a 128-bit type.
* Store `STR` with base and index. Does `x[y] = z`. There is also store-pair which does `x[a]=y, x[a+1]=z`, but as with `EXTR` above, this is basically `x[a]=y` where `y` is 128 bits.
* Test bit and conditional branch `TBNZ/TBZ`. They do `if (x & (1 << a)) goto b;` and `if (!(x & (1 << a))) goto b;` These wouldn't likely show up in a higher-level language, because the target of a branch is not usually an explicit expression; instead, it's determined by the block structure of the code.

I didn't go through the floating-point and SIMD instruction sets carefully, but a couple worth mentioning are:

* floating point multiply-add `FMADD/FMSUB`
* `BSL` which is supercat's "cookie cutter" operation, basically bitwise `?:`.
* A variety of fancy bitwise operations for accelerating CRC / SHA / AES.
---
