# Operators

## On this Page

# Operators¶

This section describes TPC-C operators and their results:

## TPC-C Type Standards¶

If the type is not specified, in the case of all scalar operands, the operation the result is evaluated according to the C99 standard.

Scalar floating types are

`float`

and`_Bfloat16`

.Vector floating types are

`float64`

and`bfloat128`

.Integer vector types are

`char256`

,`uchar256`

,`short128`

,`ushort128`

,`int64`

,`uint64`

and tensor coordinate type`int5`

.

## Arithmetic Operators¶

### Binary Operators¶

The arithmetic operators **add** (+), **subtract** (-), and **multiply** (*)
operate on built-in integer and floating-point scalar and vector data
types. All arithmetic operators return a result of the same built-in
type (integer or floating-point) as the type of the operands, after
operand type conversion. The following cases are valid after the conversion:

The two operands are

scalars. In this case, the operation is applied, resulting in ascalar.One operand is a

scalar, and the other is avector. In this case, the scalar may be subject to the usual arithmetic conversion to the element type used by the vector operand. The scalar type is then widened to a vector that has the same number of components as the vector operand. The operation is done component-wise, resulting in thesame size vector.The two operands are

vectorsof the same type. In this case, the operation is done component-wise, resulting in thesame size vector.

**division** (/) and **remainder** (%) operators are supported by calling a TPC compiler procedure.

### Unary Operators¶

The arithmetic operators **(+ and -)** operate on built-in scalar and vector types except for bool256.
All other cases of implicit conversions are illegal.

The arithmetic post- and pre-increment and decrement operators **(– and ++)**
operate on built-in scalar and integer vector types. All
unary operators work component-wise on their operands. These result
with the same type they operated on. For post- and pre-increment and
decrement, the expression must be one that could be assigned to
l-value.

Pre-increment and pre-decrement add or subtract 1 to the contents of the expression they operate on, and the value of the pre-increment or pre-decrement expression is the resulting value of that modification. Post-increment and post-decrement expressions add or subtract 1 to the contents of the expression they operate on, but the resulting expression has the expression’s value before the post-increment or post-decrement was executed.

Note

The pre- and post- increment operators may have an unexpected behavior on floating-point values and are, therefore, not supported for floating-point scalar and vector built-in types.

## Relational Operators¶

The relational operators are greater than (>), less than (<), greater than or equal (>=), less than or equal (<=).

Quality operators are equal (==), not equal to(!=) operate only on scalar types and result in an integer type.

The relational operators return 0 if the specified relation is false, and 1 if the specified relation is true. The relational and equality operators always return 0 if either argument is not a number (NaN).

## Bitwise Operators¶

The bitwise operators and (&), or (|), exclusive or (^), not (~) operate on all scalar and vector built-in types except the built-in scalar and vector float types. For vector built-in types, the operators are applied component-wise. If one operand is a scalar and the other is a vector, the scalar may be subject to the usual arithmetic conversion to the element type used by the vector operand. The scalar type is then widened to a vector that has the same number of components as the vector operand.

The operation is done component-wise, resulting in the same size vector.

## Logical Operators¶

### Binary Operators¶

The logical operators and (&&), or (||) operate on all scalar and
vector built-in types. For **scalar built-in** types only, and (&&)
only evaluates the right hand operand if the left hand operand
compares unequal to 0. For scalar built-in types only, or (||)
only evaluates the right hand operand if the left hand operand
compares equal to 0. For built-in vector types, both operands are
evaluated, and the operators are applied component-wise. If one
operand is a scalar and the other is a vector, then the scalar may be
subject to the usual arithmetic conversion to the element type used
by the vector operand. The scalar type then widens to a vector
that has the same number of components as the vector operand. The
operation is done component-wise, resulting in the same size vector.
The logical operator exclusive or (^^) is reserved.

The result is a scalar signed integer of type int if the source operands are scalar, and a vector signed integer type of the same size as the source operands if the source operands are vector types. Vector source operands of type

**char256**and**uchar256**return a**char256**result; vector source operands of type**bfloat128**,**short128**and**ushort128**return a**short128**result; vector source operands of type**int64**,**uint64**and**float64**return an**int64**result.For scalar types, the logical operators return 0 if the result of the operation is false, and 1 if the result is true. For vector types, the logical operators are evaluated component-wise return 0 if the result of the operation is false, and –1 (i.e. all bits set) if the result is true.

### Unary Operators¶

The logical unary operator not (!) operates on all scalar and vector built-in types. For built-in vector types, the operators are applied component-wise.

The result is a scalar signed integer of type int if the source operands are scalar, and a vector signed integer type of the same size as the source operands if the source operands are vector types. Vector source operands of type

**char256**and**uchar256**return a**char256**result; vector source operands of type**bfloat128**,**short128**and**ushort128**return a**short128**result; vector source operands of type**int64**,**uint64**and**float64**return an**int64**result.For scalar types, the result of the logical unary operator is 0 if the value of its operand compares unequal to 0, and 1 if the value of its operand compares equal to 0. For vector types, the unary operator returns a 0 if the value of its operand compares unequal to 0, and -1 (i.e. all bits set) if the value of its operand compares equal to 0.

### Ternary Operators¶

The **ternary** selection operator (?:) operates on three expressions
(exp1 ? exp2 : exp3). This operator evaluates the first expression
exp1, which can be a scalar only. The operator selects to evaluate
the second expression if the result compares unequal to 0, otherwise
it selects to evaluate the third expression. The second and third
expressions can be any type, as long their types match, or
implicit conversions can be applied to one of the expressions to
make their types match, or one is a vector and the other is a scalar
and the scalar may be subject to the usual arithmetic conversion to
the element type used by the vector operand and widened to the same
type as the vector type.

Note

This resulting matching type is the type of the entire expression.

## Right Shift and Left Shift Operators in C/C++¶

The operators right-shift (>>), left-shift (<<) operate on all integer and floating scalar and vector built-in types. For built-in vector types, the operators are applied component-wise. For the right-shift (>>), left-shift (<<) operators, the rightmost operand must be a scalar if the first operand is a scalar, and the rightmost operand can be a uchar256 or scalar if the first operand is a vector.

The result of E1 << E2 is E1 left-shifted by log 2 (N) least significant bits in E2 viewed as an unsigned integer value, where N is the number of bits used to represent the data type of E1 after integer promotion, if E1 is a scalar, or the number of bits used to represent the type of E1 elements, if E1 is a vector. Zeros fill the vacated bits.

The result of E1 >> E2 is E1 right-shifted by log 2 (N) least significant bits in E2 viewed as an unsigned integer value, where N is the number of bits used to represent the data type of E1 after integer promotion when E1 is a scalar, or the number of bits used to represent the type of E1 elements when E1 is a vector. If E1 has an unsigned type or if E1 has a signed type and a nonnegative value, zeros fill the vacated bits. If E1 has a signed type and a negative value, ones fill the vacated bits.

## sizeof Operator¶

The **sizeof** operator yields the size (in bytes) of its operand,
which may be an expression or the parenthesized name of a type. The
type of the operand determins the size.

The result is of type size_t. If the type of the operand is a fixed length array type, the operand is evaluated; otherwise, the operand is not evaluated, and the result is an integer constant.

When applied to an operand that has type `_Bool`

, char, uchar, the
result is 1. When applied to an operand that has type short, ushort,
or _Bfloat16 the result is 2. When applied to an operand that has
type int, uint or float, the result is 4. When applied to an operand
that is bool256 result is 32. For integer and float vector types, the
result is 256 (equal to number of components * size of each scalar
component). When applied to an operand that has array type, the
result is the total number of bytes in the array.

When applied to an operand that has structure or union type, the
result is the total number of bytes in such an object, including
internal and trailing padding. The **sizeof** operator is not
applied to an expression that has function type or an incomplete type,
or to the parenthesized name of such a type.

## Memory Operands¶

The unary (*) operator denotes indirection. If the operand points to an object, the result is a lvalue designating the object. If the operand has type ‘‘pointer to type’’, the result has type ‘‘type’’. If the pointer is assigned an invalid value, then the behavior of the unary * operator is undefined.

The unary (&) operator returns the address of its operand in local memory (see Address Space Qualifiers). If the operand has type ‘‘type’’, the result has type ‘‘pointer to type’’. If the operand is the result of a unary * operator, neither that operator nor the & operator is evaluated, and the result is as if both were omitted, except that the constraints on the operators still apply and the result is not a lvalue.

Note

If the operand is the result of a [] operator, neither the (&) operator nor the unary (*) that is implied by the [] is evaluated and the result is as if the (&) operator is removed and the [] operator is changed to a (+) operator. Otherwise, the result is a pointer to the object designated by its operand.

## Assignment Operator¶

The assignment operator ( = ) assigns values to variable names, like lvalue = expression.

The assignment operator stores the value of expression into lvalue. The expression and lvalue must have the same type, or the expression must have a type described in Table 1, in which case an implicit conversion is done on the expression before the assignment is done.

If expression is a scalar type and lvalue is a vector type, the scalar is converted to the element type used by the vector operand. The scalar type is then widened to a vector that has the same number of components as the vector operand. The operation is done component-wise resulting in the same size vector.

Any other desired type-conversions must be specified explicitly. L-values must be writable.

Variables that are built-in types, entire structures or arrays, structure fields, l-values with the field selector ( . ) applied to select components or swizzles without repeated fields, l-values within parentheses, and l-values dereferenced with the array subscript operator ( [ ] ) are all l-values. Other binary or unary expressions, function names, swizzles with repeated fields, and constants cannot be l-values. The ternary operator (?:) is also not allowed as an l-value.

The order of evaluation of the operands is unspecified. If an attempt is made to modify the result of an assignment operator or to access it after the next sequence point, then the behavior is undefined. Other assignment operators are the assignments add into (+=), subtract from (-=), multiply into (*=), divide into (/=), modulus into (%=), left shift by (<<=), right shift by (>>=), and into (&=), inclusive or into (|=), and exclusive or into (^=).

Note

`lvalue op= expression`

is equivalent to `lvalue = lvalue op expression`

.
and the l-value and expression must satisfy the requirements for both operator op and assignment (=).

## Comma Operator¶

The comma (,) operator operates on expressions by returning the type and value of the right-most expression in a comma separated list of expressions. All expressions are evaluated, in order, from left to right.