OpenSearch/docs/painless/painless-operators-numeric.asciidoc
Nik Everett fce1bbc20e Docs: Drop inline callouts from painless book (#40805)
Drops the inline callouts from the painless reference book. These
callouts are incompatible with Asciidoctor and we'd very much like to
switch to Asciidoctor for building this book, partially because
Asciidoctor is actively developed and AsciiDoc is not, and partially
because it builds the book three times faster.
2019-04-04 09:53:56 -04:00

1339 lines
32 KiB
Plaintext

[[painless-operators-numeric]]
=== Operators: Numeric
[[post-increment-operator]]
==== Post Increment
Use the `post increment operator '++'` to INCREASE the value of a numeric type
variable/field by `1`. An extra implicit cast is necessary to return the
promoted numeric type value to the original numeric type value of the
variable/field for the following types: `byte`, `short`, and `char`. If a
variable/field is read as part of an expression the value is loaded prior to the
increment.
*Errors*
* If the variable/field is a non-numeric type.
*Grammar*
[source,ANTLR4]
----
post_increment: ( variable | field ) '++';
----
*Promotion*
[options="header",cols="<1,<1,<1"]
|====
| original | promoted | implicit
| byte | int | byte
| short | int | short
| char | int | char
| int | int |
| long | long |
| float | float |
| double | double |
| def | def |
|====
*Examples*
* Post increment with different numeric types.
+
[source,Painless]
----
short i = 0; <1>
i++; <2>
long j = 1; <3>
long k; <4>
k = j++; <5>
----
+
<1> declare `short i`;
store `short 0` to `i`
<2> load from `i` -> `short 0`;
promote `short 0`: result `int`;
add `int 0` and `int 1` -> `int 1`;
implicit cast `int 1` to `short 1`;
store `short 1` to `i`
<3> declare `long j`;
implicit cast `int 1` to `long 1` -> `long 1`;
store `long 1` to `j`
<4> declare `long k`;
store default `long 0` to `k`
<5> load from `j` -> `long 1`;
store `long 1` to `k`;
add `long 1` and `long 1` -> `long 2`;
store `long 2` to `j`
+
* Post increment with the `def` type.
+
[source,Painless]
----
def x = 1; <1>
x++; <2>
----
+
<1> declare `def x`;
implicit cast `int 1` to `def` -> `def`;
store `def` to `x`
<2> load from `x` -> `def`;
implicit cast `def` to `int 1`;
add `int 1` and `int 1` -> `int 2`;
implicit cast `int 2` to `def`;
store `def` to `x`
[[post-decrement-operator]]
==== Post Decrement
Use the `post decrement operator '--'` to DECREASE the value of a numeric type
variable/field by `1`. An extra implicit cast is necessary to return the
promoted numeric type value to the original numeric type value of the
variable/field for the following types: `byte`, `short`, and `char`. If a
variable/field is read as part of an expression the value is loaded prior to
the decrement.
*Errors*
* If the variable/field is a non-numeric type.
*Grammar*
[source,ANTLR4]
----
post_decrement: ( variable | field ) '--';
----
*Promotion*
[options="header",cols="<1,<1,<1"]
|====
| original | promoted | implicit
| byte | int | byte
| short | int | short
| char | int | char
| int | int |
| long | long |
| float | float |
| double | double |
| def | def |
|====
*Examples*
* Post decrement with different numeric types.
+
[source,Painless]
----
short i = 0; <1>
i--; <2>
long j = 1; <3>
long k; <4>
k = j--; <5>
----
+
<1> declare `short i`;
store `short 0` to `i`
<2> load from `i` -> `short 0`;
promote `short 0`: result `int`;
subtract `int 1` from `int 0` -> `int -1`;
implicit cast `int -1` to `short -1`;
store `short -1` to `i`
<3> declare `long j`;
implicit cast `int 1` to `long 1` -> `long 1`;
store `long 1` to `j`
<4> declare `long k`;
store default `long 0` to `k`
<5> load from `j` -> `long 1`;
store `long 1` to `k`;
subtract `long 1` from `long 1` -> `long 0`;
store `long 0` to `j`
+
* Post decrement with the `def` type.
+
[source,Painless]
----
def x = 1; <1>
x--; <2>
----
+
<1> declare `def x`;
implicit cast `int 1` to `def` -> `def`;
store `def` to `x`
<2> load from `x` -> `def`;
implicit cast `def` to `int 1`;
subtract `int 1` from `int 1` -> `int 0`;
implicit cast `int 0` to `def`;
store `def` to `x`
[[pre-increment-operator]]
==== Pre Increment
Use the `pre increment operator '++'` to INCREASE the value of a numeric type
variable/field by `1`. An extra implicit cast is necessary to return the
promoted numeric type value to the original numeric type value of the
variable/field for the following types: `byte`, `short`, and `char`. If a
variable/field is read as part of an expression the value is loaded after the
increment.
*Errors*
* If the variable/field is a non-numeric type.
*Grammar*
[source,ANTLR4]
----
pre_increment: '++' ( variable | field );
----
*Promotion*
[options="header",cols="<1,<1,<1"]
|====
| original | promoted | implicit
| byte | int | byte
| short | int | short
| char | int | char
| int | int |
| long | long |
| float | float |
| double | double |
| def | def |
|====
*Examples*
* Pre increment with different numeric types.
+
[source,Painless]
----
short i = 0; <1>
++i; <2>
long j = 1; <3>
long k; <4>
k = ++j; <5>
----
+
<1> declare `short i`;
store `short 0` to `i`
<2> load from `i` -> `short 0`;
promote `short 0`: result `int`;
add `int 0` and `int 1` -> `int 1`;
implicit cast `int 1` to `short 1`;
store `short 1` to `i`
<3> declare `long j`;
implicit cast `int 1` to `long 1` -> `long 1`;
store `long 1` to `j`
<4> declare `long k`;
store default `long 0` to `k`
<5> load from `j` -> `long 1`;
add `long 1` and `long 1` -> `long 2`;
store `long 2` to `j`;
store `long 2` to `k`
+
* Pre increment with the `def` type.
+
[source,Painless]
----
def x = 1; <1>
++x; <2>
----
+
<1> declare `def x`;
implicit cast `int 1` to `def` -> `def`;
store `def` to `x`
<2> load from `x` -> `def`;
implicit cast `def` to `int 1`;
add `int 1` and `int 1` -> `int 2`;
implicit cast `int 2` to `def`;
store `def` to `x`
[[pre-decrement-operator]]
==== Pre Decrement
Use the `pre decrement operator '--'` to DECREASE the value of a numeric type
variable/field by `1`. An extra implicit cast is necessary to return the
promoted numeric type value to the original numeric type value of the
variable/field for the following types: `byte`, `short`, and `char`. If a
variable/field is read as part of an expression the value is loaded after the
decrement.
*Errors*
* If the variable/field is a non-numeric type.
*Grammar*
[source,ANTLR4]
----
pre_increment: '--' ( variable | field );
----
*Promotion*
[options="header",cols="<1,<1,<1"]
|====
| original | promoted | implicit
| byte | int | byte
| short | int | short
| char | int | char
| int | int |
| long | long |
| float | float |
| double | double |
| def | def |
|====
*Examples*
* Pre decrement with different numeric types.
+
[source,Painless]
----
short i = 0; <1>
--i; <2>
long j = 1; <3>
long k; <4>
k = --j; <5>
----
+
<1> declare `short i`;
store `short 0` to `i`
<2> load from `i` -> `short 0`;
promote `short 0`: result `int`;
subtract `int 1` from `int 0` -> `int -1`;
implicit cast `int -1` to `short -1`;
store `short -1` to `i`
<3> declare `long j`;
implicit cast `int 1` to `long 1` -> `long 1`;
store `long 1` to `j`
<4> declare `long k`;
store default `long 0` to `k`
<5> load from `j` -> `long 1`;
subtract `long 1` from `long 1` -> `long 0`;
store `long 0` to `j`
store `long 0` to `k`;
+
* Pre decrement operator with the `def` type.
+
[source,Painless]
----
def x = 1; <1>
--x; <2>
----
+
<1> declare `def x`;
implicit cast `int 1` to `def` -> `def`;
store `def` to `x`
<2> load from `x` -> `def`;
implicit cast `def` to `int 1`;
subtract `int 1` from `int 1` -> `int 0`;
implicit cast `int 0` to `def`;
store `def` to `x`
[[unary-positive-operator]]
==== Unary Positive
Use the `unary positive operator '+'` to the preserve the IDENTITY of a
numeric type value.
*Errors*
* If the value is a non-numeric type.
*Grammar*
[source,ANTLR4]
----
unary_positive: '+' expression;
----
*Examples*
* Unary positive with different numeric types.
+
[source,Painless]
----
int x = +1; <1>
long y = +x; <2>
----
+
<1> declare `int x`;
identity `int 1` -> `int 1`;
store `int 1` to `x`
<2> declare `long y`;
load from `x` -> `int 1`;
identity `int 1` -> `int 1`;
implicit cast `int 1` to `long 1` -> `long 1`;
store `long 1` to `y`
+
* Unary positive with the `def` type.
+
[source,Painless]
----
def z = +1; <1>
int i = +z; <2>
----
<1> declare `def z`;
identity `int 1` -> `int 1`;
implicit cast `int 1` to `def`;
store `def` to `z`
<2> declare `int i`;
load from `z` -> `def`;
implicit cast `def` to `int 1`;
identity `int 1` -> `int 1`;
store `int 1` to `i`;
[[unary-negative-operator]]
==== Unary Negative
Use the `unary negative operator '-'` to NEGATE a numeric type value.
*Errors*
* If the value is a non-numeric type.
*Grammar*
[source,ANTLR4]
----
unary_negative: '-' expression;
----
*Examples*
* Unary negative with different numeric types.
+
[source,Painless]
----
int x = -1; <1>
long y = -x; <2>
----
+
<1> declare `int x`;
negate `int 1` -> `int -1`;
store `int -1` to `x`
<2> declare `long y`;
load from `x` -> `int 1`;
negate `int -1` -> `int 1`;
implicit cast `int 1` to `long 1` -> `long 1`;
store `long 1` to `y`
+
* Unary negative with the `def` type.
+
[source,Painless]
----
def z = -1; <1>
int i = -z; <2>
----
<1> declare `def z`;
negate `int 1` -> `int -1`;
implicit cast `int -1` to `def`;
store `def` to `z`
<2> declare `int i`;
load from `z` -> `def`;
implicit cast `def` to `int -1`;
negate `int -1` -> `int 1`;
store `int 1` to `i`;
[[bitwise-not-operator]]
==== Bitwise Not
Use the `bitwise not operator '~'` to NOT each bit in an integer type value
where a `1-bit` is flipped to a resultant `0-bit` and a `0-bit` is flipped to a
resultant `1-bit`.
*Errors*
* If the value is a non-integer type.
*Bits*
[options="header",cols="<1,<1"]
|====
| original | result
| 1 | 0
| 0 | 1
|====
*Grammar*
[source,ANTLR4]
----
bitwise_not: '~' expression;
----
*Promotion*
[options="header",cols="<1,<1"]
|====
| original | promoted
| byte | int
| short | int
| char | int
| int | int
| long | long
| def | def
|====
*Examples*
* Bitwise not with different numeric types.
+
[source,Painless]
----
byte b = 1; <1>
int i = ~b; <2>
long l = ~i; <3>
----
+
<1> declare `byte x`;
store `byte 1` to b
<2> declare `int i`;
load from `b` -> `byte 1`;
implicit cast `byte 1` to `int 1` -> `int 1`;
bitwise not `int 1` -> `int -2`;
store `int -2` to `i`
<3> declare `long l`;
load from `i` -> `int -2`;
implicit cast `int -2` to `long -2` -> `long -2`;
bitwise not `long -2` -> `long 1`;
store `long 1` to `l`
+
* Bitwise not with the `def` type.
+
[source,Painless]
----
def d = 1; <1>
def e = ~d; <2>
----
+
<1> declare `def d`;
implicit cast `int 1` to `def` -> `def`;
store `def` to `d`;
<2> declare `def e`;
load from `d` -> `def`;
implicit cast `def` to `int 1` -> `int 1`;
bitwise not `int 1` -> `int -2`;
implicit cast `int 1` to `def` -> `def`;
store `def` to `e`
[[multiplication-operator]]
==== Multiplication
Use the `multiplication operator '*'` to MULTIPLY together two numeric type
values. Rules for resultant overflow and NaN values follow the JVM
specification.
*Errors*
* If either of the values is a non-numeric type.
*Grammar*
[source,ANTLR4]
----
multiplication: expression '*' expression;
----
*Promotion*
[cols="<1,^1,^1,^1,^1,^1,^1,^1,^1"]
|====
| | byte | short | char | int | long | float | double | def
| byte | int | int | int | int | long | float | double | def
| short | int | int | int | int | long | float | double | def
| char | int | int | int | int | long | float | double | def
| int | int | int | int | int | long | float | double | def
| long | long | long | long | long | long | float | double | def
| float | float | float | float | float | float | float | double | def
| double | double | double | double | double | double | double | double | def
| def | def | def | def | def | def | def | def | def
|====
*Examples*
* Multiplication with different numeric types.
+
[source,Painless]
----
int i = 5*4; <1>
double d = i*7.0; <2>
----
+
<1> declare `int i`;
multiply `int 4` by `int 5` -> `int 20`;
store `int 20` in `i`
<2> declare `double d`;
load from `int i` -> `int 20`;
promote `int 20` and `double 7.0`: result `double`;
implicit cast `int 20` to `double 20.0` -> `double 20.0`;
multiply `double 20.0` by `double 7.0` -> `double 140.0`;
store `double 140.0` to `d`
+
* Multiplication with the `def` type.
+
[source,Painless]
----
def x = 5*4; <1>
def y = x*2; <2>
----
<1> declare `def x`;
multiply `int 5` by `int 4` -> `int 20`;
implicit cast `int 20` to `def` -> `def`;
store `def` in `x`
<2> declare `def y`;
load from `x` -> `def`;
implicit cast `def` to `int 20`;
multiply `int 20` by `int 2` -> `int 40`;
implicit cast `int 40` to `def` -> `def`;
store `def` to `y`
[[division-operator]]
==== Division
Use the `division operator '/'` to DIVIDE one numeric type value by another.
Rules for NaN values and division by zero follow the JVM specification. Division
with integer values drops the remainder of the resultant value.
*Errors*
* If either of the values is a non-numeric type.
* If a left-hand side integer type value is divided by a right-hand side integer
type value of `0`.
*Grammar*
[source,ANTLR4]
----
division: expression '/' expression;
----
*Promotion*
[cols="<1,^1,^1,^1,^1,^1,^1,^1,^1"]
|====
| | byte | short | char | int | long | float | double | def
| byte | int | int | int | int | long | float | double | def
| short | int | int | int | int | long | float | double | def
| char | int | int | int | int | long | float | double | def
| int | int | int | int | int | long | float | double | def
| long | long | long | long | long | long | float | double | def
| float | float | float | float | float | float | float | double | def
| double | double | double | double | double | double | double | double | def
| def | def | def | def | def | def | def | def | def
|====
*Examples*
* Division with different numeric types.
+
[source,Painless]
----
int i = 29/4; <1>
double d = i/7.0; <2>
----
+
<1> declare `int i`;
divide `int 29` by `int 4` -> `int 7`;
store `int 7` in `i`
<2> declare `double d`;
load from `int i` -> `int 7`;
promote `int 7` and `double 7.0`: result `double`;
implicit cast `int 7` to `double 7.0` -> `double 7.0`;
divide `double 7.0` by `double 7.0` -> `double 1.0`;
store `double 1.0` to `d`
+
* Division with the `def` type.
+
[source,Painless]
----
def x = 5/4; <1>
def y = x/2; <2>
----
<1> declare `def x`;
divide `int 5` by `int 4` -> `int 1`;
implicit cast `int 1` to `def` -> `def`;
store `def` in `x`
<2> declare `def y`;
load from `x` -> `def`;
implicit cast `def` to `int 1`;
divide `int 1` by `int 2` -> `int 0`;
implicit cast `int 0` to `def` -> `def`;
store `def` to `y`
[[remainder-operator]]
==== Remainder
Use the `remainder operator '%'` to calculate the REMAINDER for division
between two numeric type values. Rules for NaN values and division by zero follow the JVM
specification.
*Errors*
* If either of the values is a non-numeric type.
*Grammar*
[source,ANTLR4]
----
remainder: expression '%' expression;
----
*Promotion*
[cols="<1,^1,^1,^1,^1,^1,^1,^1,^1"]
|====
| | byte | short | char | int | long | float | double | def
| byte | int | int | int | int | long | float | double | def
| short | int | int | int | int | long | float | double | def
| char | int | int | int | int | long | float | double | def
| int | int | int | int | int | long | float | double | def
| long | long | long | long | long | long | float | double | def
| float | float | float | float | float | float | float | double | def
| double | double | double | double | double | double | double | double | def
| def | def | def | def | def | def | def | def | def
|====
*Examples*
* Remainder with different numeric types.
+
[source,Painless]
----
int i = 29%4; <1>
double d = i%7.0; <2>
----
+
<1> declare `int i`;
remainder `int 29` by `int 4` -> `int 1`;
store `int 7` in `i`
<2> declare `double d`;
load from `int i` -> `int 1`;
promote `int 1` and `double 7.0`: result `double`;
implicit cast `int 1` to `double 1.0` -> `double 1.0`;
remainder `double 1.0` by `double 7.0` -> `double 1.0`;
store `double 1.0` to `d`
+
* Remainder with the `def` type.
+
[source,Painless]
----
def x = 5%4; <1>
def y = x%2; <2>
----
<1> declare `def x`;
remainder `int 5` by `int 4` -> `int 1`;
implicit cast `int 1` to `def` -> `def`;
store `def` in `x`
<2> declare `def y`;
load from `x` -> `def`;
implicit cast `def` to `int 1`;
remainder `int 1` by `int 2` -> `int 1`;
implicit cast `int 1` to `def` -> `def`;
store `def` to `y`
[[addition-operator]]
==== Addition
Use the `addition operator '+'` to ADD together two numeric type values. Rules
for resultant overflow and NaN values follow the JVM specification.
*Errors*
* If either of the values is a non-numeric type.
*Grammar*
[source,ANTLR4]
----
addition: expression '+' expression;
----
*Promotion*
[cols="<1,^1,^1,^1,^1,^1,^1,^1,^1"]
|====
| | byte | short | char | int | long | float | double | def
| byte | int | int | int | int | long | float | double | def
| short | int | int | int | int | long | float | double | def
| char | int | int | int | int | long | float | double | def
| int | int | int | int | int | long | float | double | def
| long | long | long | long | long | long | float | double | def
| float | float | float | float | float | float | float | double | def
| double | double | double | double | double | double | double | double | def
| def | def | def | def | def | def | def | def | def
|====
*Examples*
* Addition operator with different numeric types.
+
[source,Painless]
----
int i = 29+4; <1>
double d = i+7.0; <2>
----
+
<1> declare `int i`;
add `int 29` and `int 4` -> `int 33`;
store `int 33` in `i`
<2> declare `double d`;
load from `int i` -> `int 33`;
promote `int 33` and `double 7.0`: result `double`;
implicit cast `int 33` to `double 33.0` -> `double 33.0`;
add `double 33.0` and `double 7.0` -> `double 40.0`;
store `double 40.0` to `d`
+
* Addition with the `def` type.
+
[source,Painless]
----
def x = 5+4; <1>
def y = x+2; <2>
----
<1> declare `def x`;
add `int 5` and `int 4` -> `int 9`;
implicit cast `int 9` to `def` -> `def`;
store `def` in `x`
<2> declare `def y`;
load from `x` -> `def`;
implicit cast `def` to `int 9`;
add `int 9` and `int 2` -> `int 11`;
implicit cast `int 11` to `def` -> `def`;
store `def` to `y`
[[subtraction-operator]]
==== Subtraction
Use the `subtraction operator '-'` to SUBTRACT a right-hand side numeric type
value from a left-hand side numeric type value. Rules for resultant overflow
and NaN values follow the JVM specification.
*Errors*
* If either of the values is a non-numeric type.
*Grammar*
[source,ANTLR4]
----
subtraction: expression '-' expression;
----
*Promotion*
[cols="<1,^1,^1,^1,^1,^1,^1,^1,^1"]
|====
| | byte | short | char | int | long | float | double | def
| byte | int | int | int | int | long | float | double | def
| short | int | int | int | int | long | float | double | def
| char | int | int | int | int | long | float | double | def
| int | int | int | int | int | long | float | double | def
| long | long | long | long | long | long | float | double | def
| float | float | float | float | float | float | float | double | def
| double | double | double | double | double | double | double | double | def
| def | def | def | def | def | def | def | def | def
|====
*Examples*
* Subtraction with different numeric types.
+
[source,Painless]
----
int i = 29-4; <1>
double d = i-7.5; <2>
----
+
<1> declare `int i`;
subtract `int 4` from `int 29` -> `int 25`;
store `int 25` in `i`
<2> declare `double d`
load from `int i` -> `int 25`;
promote `int 25` and `double 7.5`: result `double`;
implicit cast `int 25` to `double 25.0` -> `double 25.0`;
subtract `double 33.0` by `double 7.5` -> `double 25.5`;
store `double 25.5` to `d`
+
* Subtraction with the `def` type.
+
[source,Painless]
----
def x = 5-4; <1>
def y = x-2; <2>
----
<1> declare `def x`;
subtract `int 4` and `int 5` -> `int 1`;
implicit cast `int 1` to `def` -> `def`;
store `def` in `x`
<2> declare `def y`;
load from `x` -> `def`;
implicit cast `def` to `int 1`;
subtract `int 2` from `int 1` -> `int -1`;
implicit cast `int -1` to `def` -> `def`;
store `def` to `y`
[[left-shift-operator]]
==== Left Shift
Use the `left shift operator '<<'` to SHIFT lower order bits to higher order
bits in a left-hand side integer type value by the distance specified in a
right-hand side integer type value.
*Errors*
* If either of the values is a non-integer type.
* If the right-hand side value cannot be cast to an int type.
*Grammar*
[source,ANTLR4]
----
left_shift: expression '<<' expression;
----
*Promotion*
The left-hand side integer type value is promoted as specified in the table
below. The right-hand side integer type value is always implicitly cast to an
`int` type value and truncated to the number of bits of the promoted type value.
[options="header",cols="<1,<1"]
|====
| original | promoted
| byte | int
| short | int
| char | int
| int | int
| long | long
| def | def
|====
*Examples*
* Left shift with different integer types.
+
[source,Painless]
----
int i = 4 << 1; <1>
long l = i << 2L; <2>
----
+
<1> declare `int i`;
left shift `int 4` by `int 1` -> `int 8`;
store `int 8` in `i`
<2> declare `long l`
load from `int i` -> `int 8`;
implicit cast `long 2` to `int 2` -> `int 2`;
left shift `int 8` by `int 2` -> `int 32`;
implicit cast `int 32` to `long 32` -> `long 32`;
store `long 32` to `l`
+
* Left shift with the `def` type.
+
[source,Painless]
----
def x = 4 << 2; <1>
def y = x << 1; <2>
----
<1> declare `def x`;
left shift `int 4` by `int 2` -> `int 16`;
implicit cast `int 16` to `def` -> `def`;
store `def` in `x`
<2> declare `def y`;
load from `x` -> `def`;
implicit cast `def` to `int 16`;
left shift `int 16` by `int 1` -> `int 32`;
implicit cast `int 32` to `def` -> `def`;
store `def` to `y`
[[right-shift-operator]]
==== Right Shift
Use the `right shift operator '>>'` to SHIFT higher order bits to lower order
bits in a left-hand side integer type value by the distance specified in a
right-hand side integer type value. The highest order bit of the left-hand side
integer type value is preserved.
*Errors*
* If either of the values is a non-integer type.
* If the right-hand side value cannot be cast to an int type.
*Grammar*
[source,ANTLR4]
----
right_shift: expression '>>' expression;
----
*Promotion*
The left-hand side integer type value is promoted as specified in the table
below. The right-hand side integer type value is always implicitly cast to an
`int` type value and truncated to the number of bits of the promoted type value.
[options="header",cols="<1,<1"]
|====
| original | promoted
| byte | int
| short | int
| char | int
| int | int
| long | long
| def | def
|====
*Examples*
* Right shift with different integer types.
+
[source,Painless]
----
int i = 32 >> 1; <1>
long l = i >> 2L; <2>
----
+
<1> declare `int i`;
right shift `int 32` by `int 1` -> `int 16`;
store `int 16` in `i`
<2> declare `long l`
load from `int i` -> `int 16`;
implicit cast `long 2` to `int 2` -> `int 2`;
right shift `int 16` by `int 2` -> `int 4`;
implicit cast `int 4` to `long 4` -> `long 4`;
store `long 4` to `l`
+
* Right shift with the `def` type.
+
[source,Painless]
----
def x = 16 >> 2; <1>
def y = x >> 1; <2>
----
<1> declare `def x`;
right shift `int 16` by `int 2` -> `int 4`;
implicit cast `int 4` to `def` -> `def`;
store `def` in `x`
<2> declare `def y`;
load from `x` -> `def`;
implicit cast `def` to `int 4`;
right shift `int 4` by `int 1` -> `int 2`;
implicit cast `int 2` to `def` -> `def`;
store `def` to `y`
[[unsigned-right-shift-operator]]
==== Unsigned Right Shift
Use the `unsigned right shift operator '>>>'` to SHIFT higher order bits to
lower order bits in a left-hand side integer type value by the distance
specified in a right-hand side type integer value. The highest order bit of the
left-hand side integer type value is *not* preserved.
*Errors*
* If either of the values is a non-integer type.
* If the right-hand side value cannot be cast to an int type.
*Grammar*
[source,ANTLR4]
----
unsigned_right_shift: expression '>>>' expression;
----
*Promotion*
The left-hand side integer type value is promoted as specified in the table
below. The right-hand side integer type value is always implicitly cast to an
`int` type value and truncated to the number of bits of the promoted type value.
[options="header",cols="<1,<1"]
|====
| original | promoted
| byte | int
| short | int
| char | int
| int | int
| long | long
| def | def
|====
*Examples*
* Unsigned right shift with different integer types.
+
[source,Painless]
----
int i = -1 >>> 29; <1>
long l = i >>> 2L; <2>
----
+
<1> declare `int i`;
unsigned right shift `int -1` by `int 29` -> `int 7`;
store `int 7` in `i`
<2> declare `long l`
load from `int i` -> `int 7`;
implicit cast `long 2` to `int 2` -> `int 2`;
unsigned right shift `int 7` by `int 2` -> `int 3`;
implicit cast `int 3` to `long 3` -> `long 3`;
store `long 3` to `l`
+
* Unsigned right shift with the `def` type.
+
[source,Painless]
----
def x = 16 >>> 2; <1>
def y = x >>> 1; <2>
----
<1> declare `def x`;
unsigned right shift `int 16` by `int 2` -> `int 4`;
implicit cast `int 4` to `def` -> `def`;
store `def` in `x`
<2> declare `def y`;
load from `x` -> `def`;
implicit cast `def` to `int 4`;
unsigned right shift `int 4` by `int 1` -> `int 2`;
implicit cast `int 2` to `def` -> `def`;
store `def` to `y`
[[bitwise-and-operator]]
==== Bitwise And
Use the `bitwise and operator '&'` to AND together each bit within two
integer type values where if both bits at the same index are `1` the resultant
bit is `1` and `0` otherwise.
*Errors*
* If either of the values is a non-integer type.
*Bits*
[cols="^1,^1,^1"]
|====
| | 1 | 0
| 1 | 1 | 0
| 0 | 0 | 0
|====
*Grammar*
[source,ANTLR4]
----
bitwise_and: expression '&' expression;
----
*Promotion*
[cols="<1,^1,^1,^1,^1,^1,^1"]
|====
| | byte | short | char | int | long | def
| byte | int | int | int | int | long | def
| short | int | int | int | int | long | def
| char | int | int | int | int | long | def
| int | int | int | int | int | long | def
| long | long | long | long | long | long | def
| def | def | def | def | def | def | def
|====
*Examples*
* Bitwise and with different integer types.
+
[source,Painless]
----
int i = 5 & 6; <1>
long l = i & 5L; <2>
----
+
<1> declare `int i`;
bitwise and `int 5` and `int 6` -> `int 4`;
store `int 4` in `i`
<2> declare `long l`
load from `int i` -> `int 4`;
promote `int 4` and `long 5`: result `long`;
implicit cast `int 4` to `long 4` -> `long 4`;
bitwise and `long 4` and `long 5` -> `long 4`;
store `long 4` to `l`
+
* Bitwise and with the `def` type.
+
[source,Painless]
----
def x = 15 & 6; <1>
def y = x & 5; <2>
----
<1> declare `def x`;
bitwise and `int 15` and `int 6` -> `int 6`;
implicit cast `int 6` to `def` -> `def`;
store `def` in `x`
<2> declare `def y`;
load from `x` -> `def`;
implicit cast `def` to `int 6`;
bitwise and `int 6` and `int 5` -> `int 4`;
implicit cast `int 4` to `def` -> `def`;
store `def` to `y`
[[bitwise-xor-operator]]
==== Bitwise Xor
Use the `bitwise xor operator '^'` to XOR together each bit within two integer
type values where if one bit is a `1` and the other bit is a `0` at the same
index the resultant bit is `1` otherwise the resultant bit is `0`.
*Errors*
* If either of the values is a non-integer type.
*Bits*
The following table illustrates the resultant bit from the xoring of two bits.
[cols="^1,^1,^1"]
|====
| | 1 | 0
| 1 | 0 | 1
| 0 | 1 | 0
|====
*Grammar*
[source,ANTLR4]
----
bitwise_and: expression '^' expression;
----
*Promotion*
[cols="<1,^1,^1,^1,^1,^1,^1"]
|====
| | byte | short | char | int | long | def
| byte | int | int | int | int | long | def
| short | int | int | int | int | long | def
| char | int | int | int | int | long | def
| int | int | int | int | int | long | def
| long | long | long | long | long | long | def
| def | def | def | def | def | def | def
|====
*Examples*
* Bitwise xor with different integer types.
+
[source,Painless]
----
int i = 5 ^ 6; <1>
long l = i ^ 5L; <2>
----
+
<1> declare `int i`;
bitwise xor `int 5` and `int 6` -> `int 3`;
store `int 3` in `i`
<2> declare `long l`
load from `int i` -> `int 4`;
promote `int 3` and `long 5`: result `long`;
implicit cast `int 3` to `long 3` -> `long 3`;
bitwise xor `long 3` and `long 5` -> `long 6`;
store `long 6` to `l`
+
* Bitwise xor with the `def` type.
+
[source,Painless]
----
def x = 15 ^ 6; <1>
def y = x ^ 5; <2>
----
<1> declare `def x`;
bitwise xor `int 15` and `int 6` -> `int 9`;
implicit cast `int 9` to `def` -> `def`;
store `def` in `x`
<2> declare `def y`;
load from `x` -> `def`;
implicit cast `def` to `int 9`;
bitwise xor `int 9` and `int 5` -> `int 12`;
implicit cast `int 12` to `def` -> `def`;
store `def` to `y`
[[bitwise-or-operator]]
==== Bitwise Or
Use the `bitwise or operator '|'` to OR together each bit within two integer
type values where if at least one bit is a `1` at the same index the resultant
bit is `1` otherwise the resultant bit is `0`.
*Errors*
* If either of the values is a non-integer type.
*Bits*
The following table illustrates the resultant bit from the oring of two bits.
[cols="^1,^1,^1"]
|====
| | 1 | 0
| 1 | 1 | 1
| 0 | 1 | 0
|====
*Grammar*
[source,ANTLR4]
----
bitwise_and: expression '|' expression;
----
*Promotion*
[cols="<1,^1,^1,^1,^1,^1,^1"]
|====
| | byte | short | char | int | long | def
| byte | int | int | int | int | long | def
| short | int | int | int | int | long | def
| char | int | int | int | int | long | def
| int | int | int | int | int | long | def
| long | long | long | long | long | long | def
| def | def | def | def | def | def | def
|====
*Examples*
* Bitwise or with different integer types.
+
[source,Painless]
----
int i = 5 | 6; <1>
long l = i | 8L; <2>
----
+
<1> declare `int i`;
bitwise or `int 5` and `int 6` -> `int 7`;
store `int 7` in `i`
<2> declare `long l`
load from `int i` -> `int 7`;
promote `int 7` and `long 8`: result `long`;
implicit cast `int 7` to `long 7` -> `long 7`;
bitwise or `long 7` and `long 8` -> `long 15`;
store `long 15` to `l`
+
* Bitwise or with the `def` type.
+
[source,Painless]
----
def x = 5 ^ 6; <1>
def y = x ^ 8; <2>
----
<1> declare `def x`;
bitwise or `int 5` and `int 6` -> `int 7`;
implicit cast `int 7` to `def` -> `def`;
store `def` in `x`
<2> declare `def y`;
load from `x` -> `def`;
implicit cast `def` to `int 7`;
bitwise or `int 7` and `int 8` -> `int 15`;
implicit cast `int 15` to `def` -> `def`;
store `def` to `y`