//
// This confidential and proprietary software may be used only as
// authorised by a licensing agreement from ARM Limited
// (C) COPYRIGHT 2020-2021 ARM Limited
// ALL RIGHTS RESERVED
// The entire notice above must be reproduced on all authorised
// copies and copies may only be made to the extent permitted
// by a licensing agreement from ARM Limited.

=== Elementwise Unary Operators

==== ABS

Elementwise absolute value operation

*Arguments:*

|===
|Argument|Type|Name|Shape|Description

|Input|in_t*|input1|shape|Input tensor
|Output|in_t*|output|shape|Output tensor of same type, size as the input tensor
|===

*Operation Function:*

[source,c++]
----
for_each(index in shape) {
    in_t value1 = tensor_read<in_t>(input1, shape, index);
    if (value1 < 0)
        value1 = apply_sub<in_t>(0, value1);
    tensor_write<in_t>(output, shape, index, value1);
}
----

*Supported Data Types:*

|===
|Profile|Mode|in_t

|Any|signed 32|int32_t
|MI, MT|floating-point|float_t
|===

==== BITWISE_NOT

Elementwise bitwise NOT of input tensor.

*Arguments:*

|===
|Argument|Type|Name|Shape|Description

|Input|in_t*|input1|shape|Input tensor
|Output|in_t*|output|shape|Output tensor of same type, size as the input tensor
|===

*Quantization Parameters:*

None

*Operation Function:*

[source,c++]
----
for_each(index in shape) {
    in_t value1 = tensor_read<in_t>(input1, shape, index);
    in_t acc = ~value1;
    tensor_write<in_t>(output, shape, index, acc);
}
----

*Supported Data Types:*

|===
|Profile|Mode|in_t

|Any|signed 8|int8_t
|Any|signed 16|int16_t
|Any|signed 32|int32_t
|===

==== CEIL

Elementwise ceiling operation

*Arguments:*

|===
|Argument|Type|Name|Shape|Description

|Input|in_t*|input1|shape|Input tensor
|Output|in_t*|output|shape|Output tensor of same type, size as the input tensor
|===

*Supported Data Types:*

|===
|Profile|Mode|in_t

|MI, MT|floating-point|float_t
|===

==== CLZ

Elementwise count leading zeros operation

*Arguments:*

|===
|Argument|Type|Name|Shape|Description

|Input|in_t*|input1|shape|Input tensor
|Output|in_t*|output|shape|Output tensor of same type, size as the input tensor
|===

*Operation Function:*

[source,c++]
----
for_each(index in shape) {
    in_t acc = 0;
    in_t value1 = tensor_read<in_t>(input1, shape, index);
    acc = count_leading_zeros(value1);
    tensor_write<in_t>(output, shape, index, acc);
}
----

*Supported Data Types:*
|===
|Profile|Mode|in_t

|Any|signed 32|int32_t
|===

==== EXP

Elementwise e to the x operation

*Arguments:*

|===
|Argument|Type|Name|Shape|Description

|Input|in_t*|input1|shape|Input tensor
|Output|in_t*|output|shape|Output tensor of same type, size as the input tensor
|===

*Supported Data Types:*

|===
|Profile|Mode|in_t

|MI, MT|floating-point|float_t
|===

==== FLOOR

Elementwise floor operation

*Arguments:*

|===
|Argument|Type|Name|Shape|Description

|Input|in_t*|input1|shape|Input tensor
|Output|in_t*|output|shape|Output tensor of same type, size as the input tensor
|===

*Supported Data Types:*

|===
|Profile|Mode|in_t

|MI, MT|floating-point|float_t
|===

==== LOG

Elementwise natural logarithm operation

*Arguments:*

|===
|Argument|Type|Name|Shape|Description

|Input|in_t*|input1|shape|Input tensor
|Output|in_t*|output|shape|Output tensor of same type, size as the input tensor
|===

*Supported Data Types:*

|===
|Profile|Mode|in_t

|MI, MT|floating-point|float_t
|===

==== LOGICAL_NOT

Elementwise logical NOT of input.

*Arguments:*

|===
|Argument|Type|Name|Shape|Description

|Input|in_t*|input1|shape|Input tensor
|Output|in_t*|output|shape|Output tensor of same type, size as the input tensor
|===

*Quantization Parameters:*

None

*Operation Function:*

[source,c++]
----
for_each(index in shape) {
    in_t value1 = tensor_read<in_t>(input1, shape1, index);
    in_t acc = !value1;
    tensor_write<in_t>(output, shape, index, acc);
}
----

*Supported Data Types:*

|===
|Profile|Mode|in_t

|Any|bool|bool_t
|===

==== NEGATE

Elementwise negation operation

*Arguments:*

|===
|Argument|Type|Name|Shape|Description

|Input|in_t*|input1|shape|Input tensor
|Output|in_t*|output|shape|Output tensor of same type, size as the input tensor
|===

*Quantization Parameters:*

|===
|Argument|Type|Name|Shape|Description

|Attribute|in_t|input1_zp|-|Input 1 zero point
|Attribute|in_t|output_zp|-|Output zero point
|===

*Operation Function:*

[source,c++]
----
assert(in_t == int8_t || input1_zp == 0) // Zero point only for int8_t
assert(in_t == int8_t || output_zp == 0) // Zero point only for int8_t
for_each(index in shape) {
    acc_t acc = tensor_read<in_t>(input1, shape, index, input1_zp);
    acc = apply_sub<acc_t>(0, acc);
    in_t value = (in_t)apply_clip<acc_t>(acc + output_zp, minimum<in_t>, maximum<in_t>);
    tensor_write<in_t>(output, shape, index, value);
}
----

*Supported Data Types:*

|===
|Profile|Mode|in_t|acc_t

|Any|signed 8|int8_t|int32_t
|Any|signed 16|int16_t|int32_t
|Any|signed 32|int32_t|int32_t
|MI, MT|floating-point|float_t|float_t
|===

==== RECIPROCAL

Elementwise reciprocal operation. For integer operation, a TABLE should be used with the appropriate ranges.

*Arguments:*

|===
|Argument|Type|Name|Shape|Description

|Input|in_t*|input1|shape|Input tensor
|Output|in_t*|output|shape|Output tensor of same type, size as the input tensor
|===

*Supported Data Types:*

|===
|Profile|Mode|in_t

|MI, MT|floating-point|float_t
|===

==== RSQRT

Elementwise reciprocal square root operation. For integer operation, a TABLE should be used with the appropriate ranges.

*Arguments:*

|===
|Argument|Type|Name|Shape|Description

|Input|in_t*|input1|shape|Input tensor
|Output|in_t*|output|shape|Output tensor of same type, size as the input tensor
|===

*Supported Data Types:*

|===
|Profile|Mode|in_t

|MI, MT|floating-point|float_t
|===
