# Abs, Neg, and Saturate

Preferred way to use abs/neg/saturate functions

On PowerVR architecture, it is essential to use modifiers such as `abs()`, `neg()`, and `clamp(…, 0.0, 1.0)` (also known as `saturate()`) - being free in certain cases.

`abs()` and `neg()` are free if they are used on an input to an operation, in which case they are turned into a free modifier by the compiler. However, `saturate()` turns into a free modifier when used on the output of an operation.

Note: Complex and sampling/interpolation instructions are exceptions to this rule. `saturate()` is not free when used on a texture sampling output, or on a complex instruction output. When these functions are not used accordingly, they may introduce additional `MOV` instructions which may increase the cycle count of the shaders.

It is also beneficial to use `clamp(…, 0.0, 1.0)` instead of `min(…, 1.0)` and `max(…, 0.0)`. This changes a test instruction into a saturate modifier:

```fragColor.x = abs(t.x * t.y); // two cycles
{sop, sop}
{mov, mov, mov}
-->
fragColor.x = abs(t.x) * abs(t.y); // one cycle
{sop, sop}
fragColor.x = -dot(t.xyz, t.yzx); // three cycles
{sop, sop, sopmov}
{sop, sop}
{mov, mov, mov}
-->
fragColor.x = dot(-t.xyz, t.yzx); // two cycles
{sop, sop, sopmov}
{sop, sop}
fragColor.x = 1.0 - clamp(t.x, 0.0, 1.0); // two cycles
{sop, sop, sopmov}
{sop, sop}
-->
fragColor.x = clamp(1.0 - t.x, 0.0, 1.0); // one cycle
{sop, sop}
fragColor.x = min(dot(t, t), 1.0) > 0.5 ? t.x : t.y; // five cycles
{sop, sop, sopmov}
{sop, sop}
{mov, mov, pck, tstg, mov}
{mov, mov, tstz, mov}
-->
fragColor.x = clamp(dot(t, t), 0.0, 1.0) > 0.5 ? t.x : t.y; // four cycles
{sop, sop, sopmov}
{sop, sop}
{mov, mov, tstz, mov}```

However, it is sensible to be wary of complex functions, as they are translated into multiple operations. Therefore in this case it matters where the modifiers are placed.

For example, `normalize()` is broken down into:

```vec3 normalize( vec3 v )
{
return v * inverssqrt( dot( v, v ) );
}```

In this case it is best to negate one of the inputs of the final multiplication rather than the inputs in all cases, or create a temporary negated input:

```fragColor.xyz = -normalize(t.xyz); // six cycles
{fmul, mov}