# pow(x, 2) different then x*x?

• 10-01-2013, 10:28 PM
Osbios
pow(x, 2) different then x*x?
I have this two lines and they result in completely different results, and I don't know why.

Code :

```vec3 normal = vec3(normalTex.x, normalTex.y, sqrt(abs(normalTex.x * normalTex.x + normalTex.y * normalTex.y - 1.0f))); vec3 normal = vec3(normalTex.x, normalTex.y, sqrt(abs(pow(normalTex.x, 2.0f) + pow(normalTex.y, 2.0f) - 1.0f)));```

normalTex.x and normalTex.y are in the range -1..1

Do I have a brain fart or can I point fingers at GPU drivers?
• 10-02-2013, 04:54 AM
Dark Photon
If you look up pow(x,y) in the GLSL programming guide, you'll see that its not defined where x < 0 (and also when x == 0 and y <= 0). The reason is that it is implemented as:

pow(x,y) = exp2 (y * log2 (x))

and the log isn't defined for values <= 0.

Note that the GLSL 4.4 spec has a bug here; it says that pow() is actually implemented as:

pow(x,y) = exp2 (x * log2 (y))

which (unless I need more caffeine this morning) is wrong.
• 10-02-2013, 01:24 PM
GClements
Quote:

Originally Posted by Osbios
normalTex.x and normalTex.y are in the range -1..1

The documentation for pow() says:
Quote:

Results are undefined if x < 0.
In general, raising a negative value to a fractional power produces a complex result. There are specific cases where the imaginary part of the result is zero (e.g. if the fractional part of the exponent is zero, or the exponent is the reciprocal of an odd integer), but there isn't a general algorithm which can handle these cases without involving complex numbers. In particular, implementing pow(x,y) as exp(log(x)*y) will result in a domain error from log() if x is negative and log() only understands real numbers.

With complex numbers, log() of a negative number will produce an complex number whose imaginary part is π, multiplying by an integer produces a complex number whose imaginary part is an integer multiple of π, and raising e to a complex number whose imaginary part is an integer multiple of π produces a real number (by Euler's identity, eix = cos(x) + i*sin(x), and sin(n*π)=0 for any integer n). Using a different base just results in a factor of logbase(e) from logbase which is cancelled out by expbase.
Quote:

Originally Posted by Osbios
Do I have a brain fart or can I point fingers at GPU drivers?

.
The drivers aren't at fault. And I doubt that The Powers That Be consider GLSL's lack of support for complex numbers to be a bug per se.
• 10-02-2013, 02:07 PM
Osbios
More of a brain fart then, but to my defense the ref I looked up at the time didn't mention this limitation. Also my first assumption was pow(x, 2) to be resolved as x * x.
• 10-02-2013, 03:13 PM
mhagain
Some compilers might resolve it that way, but it's not guaranteed.

I'd be more inclined to write this as "dot (normalTex.xy, normalTex.xy)" anyway, which should optimize better.
• 10-03-2013, 02:16 AM
GClements
Quote:

Originally Posted by Osbios
Also my first assumption was pow(x, 2) to be resolved as x * x.

The problem with that is that both arguments to pow() are floats (or vectors of floats), and interpreting exponentiation as "repeated multiplication" is only meaningful when the exponent is an integer.

In practical terms, that means "when the exponent is required to be an integer", not "when it happens to be an integer". Explicitly checking for integer exponents and selecting a different implementation would have a cost either in GPU cycles or in silicon.

If you want to calculate a square, use x*x. pow() is intended for the general case (e.g. specular exponent).