I´m having some problem when calling pow() on a RP2040 connect and Raspberry pico. In my project I have a test suite to verify that I get the same result from different platforms. The test case that fails on the RP2040 is when I call pow(0,-1). The result should be +inf but I get -inf.
I have created a smaller example to mimic the behavior from my project . If I call pow() from inside the loop function I get correct result but if I call pow from the function_pow I get wrong result.
Any idea why this happens?
#include "Arduino.h"
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
}
double function_pow(double base, double power)
{
double result = 0.0;
result = pow(base, power);
Serial.print("result inside function pow(0,-1) = "); Serial.println(result);
Serial.println(*(int64_t*)&result);
if(isnan(result)) return 0; // for simple printf debugging
if (isinf(result) && result<0.0)
{
Serial.println("Bad: Inside function, Yes I'm infinity and <0.0");
}
else if (isinf(result) && result>0.0)
{
Serial.println("Good: Inside function, Yes I'm infinity and >0.0");
}
return result;
}
void loop() {
// put your main code here, to run repeatedly:
double res = function_pow(0.0,-1.0);
Serial.print("result from function_pow(0,-1) = "); Serial.println(res);
Serial.println("*****************");
double dres = pow(0.0,-1.0);
Serial.println(*(int64_t*)&dres);
if(isnan(dres)) Serial.println("I'm nan");
else if (isinf(dres) && dres<0.0)
{
Serial.println("Bad: Yes I'm infinity and <0.0");
}
else if (isinf(dres) && dres>0.0)
{
Serial.println("Good: Yes I'm infinity and >0.0");
}
Serial.println("####################");
}
And the result when running the code
###################
result inside function pow(0,-1) = inf
-4503599627370496
Bad: Inside function, Yes I'm infinity and <0.0
result from function_pow(0,-1) = inf
*****************
9218868437227405312
Good: Yes I'm infinity and >0.0
I don't have RP2040 but tecnically (maths says...) zero to the power of -1 is 1/0 that is undefined by definition, so it doesn't matter if "-inf" or "+inf", it's still an undefined value!
Why does it seems you a wrong result? Why can't you just ignore the difference and treat it like what it is, an infinite (better, undefined) value?
Btw, "result" variable is a double, so I wonder why you added this to treat it as an unsigned long:
Serial.println(*(int64_t*)&result);
it seems to me like there's a missing final explicit cast:
And running your code on Wokwi (I know, here "double" is just a "float"), it goes like:
result inside function pow(0,-1) = inf
2139095040
Good: Inside function, Yes I'm infinity and >0.0
result from function_pow(0,-1) = 2139095040
*****************
inf
Good: Yes I'm infinity and >0.0
####################
0/0 is undefined (NaN) in IEEE754, but 1/0 is defined as +Infinity. The problem in this example is that I get two different results depending on the context in which I process the results from pow . +Infinity is the correct answer and I get that in the outer loop. But in the separate function I get -Infinity which is wrong. This seems to be a compiler error.
+inf is always greater than zero (and -inf is always less than zero). On the other hand, you can't compare nan with anything though. All comparisons with nan are false, even "nan == nan" is false.
Yes, but let me point again it's just a convention especially for programming languages, because, speaking of mathematics, 1/0 is just "undefined", nothing more nothing less, nothing else.
You can call it whatever one likes, "-inf", "+inf", "jack" or "foo", it doesn't matter. And you can do nothing with such element even if you make it equivalent to infinite (you can't add, subtract or compare infinite(s).
Returning to programming, when this value comes out, it is something that you cannot/do not accept and you must do something to avoid any blocking or anomalous behavior of the program.
Back to the OP who rightly asks why there is this apparent difference for a similar operation, given that the problem could lie in the way in which the compiler optimizes the code, my answer is simply "I don't know, but what does it matter anyway? ".
Even in mathematics, +inf is always greater than 0. I didn't say anything about 1/0. Infinities are well-defined and well-behaved in C++ and IEEE 754.
In IEEE 754, powr(x, y) is defined as exp(y * log(x)), and for x=0 and y<0, the output is defined as +inf and should raise a divide by zero exception. C++ also defines pow(x, y) as exp(y * log(x)). See the section "26.4.8 Transcendentals" in https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/n4849.pdf:
20 Returns: The complex power of base x raised to the yth power, defined as exp(y * log(x)). The value returned for pow(0, 0) is implementation-defined.
So if pow(0, -1) returns anything besides +inf then it's a bug (or at least not conforming to IEEE 754).
Nah. Please, don't say inaccurate or misleading things.
First, we must always remember an infinite is "infinite", and in maths there's no way to compare it with any real number and determine if it's greater or not.
And about +inf and -inf we're discussing about, start searching for y=1/x graph:
You can clearly see it's just UNDEFINED for x=0, because if you move from x>0 towards zero (limit for x+ tending to 0), it tends to "+inf", if you move from x<0 it tends to "-inf".
But for x=0 it is undefined, no doubt about it, so any representation you want/need to use is matematically wrong. Or at least just a convention you use/adopt (like C++ and IEEE 754), but it's just your choice: it is valid just for that convention and not generally speaking and not matematically speaking.
Now, however, on my side I will stop debating on this topic, given that whatever interpretation to give to the expression 1/0 in this context (Arduino programming) is not strictly linked to our academic discussions on mathematics, and if a function can provide " +inf" in one case and "-inf" in another is a condition that makes no sense, and should just be treated as "infinite" (or, better, an error).
Greetings.
Mathematics depends on a number of paradigms in order to define it.
For example the mathematical paradigm that parallel lines do not converge gives us plain geometry but if you change that paradigm to parallel lines do converge then we get spherical geometry, which is great for living on a planet.
Now there is a paradigm that allows for none contiguous functions, like 1/x or Tan(x).
Suppose that this paradigm forbids none contiguous functions, then we reach the conclusion that negative infinity is at exactly the same place as positive infinity.
Who knows what sort of Universe that is useful for, I am sure The Doctor does.
Well, even if I studied as an Engineer (yeah, I'm pretty old, as I'm 64), I've always been attracted by maths and physics, particularly relativity (SR/GR), quantum mechanics, astrophysics and cosmology, doing my best in studying those subjects in my spare time even if I don't have the deep maths basics to fully understand many descriptions. I like to keep my mind active and updated. (side note: my daughter probabily got that from me, so ten years ago she graduated in Astrophysics, then works as an astrophysics researcher, and she's now a physics professor at Pittsburgh CMU).
Said that, sorry for this personal digression, I won't go on with that OT.
Yes, it's the classic "non-euclidean geometry". Out Univeerse too, could be a 4-dimensions sphere...
Now going back to your question:
That cannnot be defined as either true or false. Even if we can handle "imaginary numbers" (e.g. they're widely used in quantum mechanics!), when dealing with infinity we can't make many assumptions as in regular maths.
Going back to the specific programming question, you know that my approach is considering -inf and +inf equivalent (they're the same "infinity", aka a "not-manageable" value, and often an error to be appropriately managed).
So I apologize to the moderators promising that I will not return to the topic again.
PS: speaking of infinity for the last time, check Numberphile out, it is one of my favorite YouTube educational channels about mathematics.
Me too I am 72, and studied Physics at undergraduate level and did an Electrical Engineering post graduate work. I lectured at a UK university which is the US equivalent of a professor, in Physics, instrumentation and astronomy.
Uh what? In mathematics, positive infinity is greater than the set of all real numbers, or in other words it is greater than any real number. (Similarly for negative infinity, except it's less than the set of all real numbers.) Zero is a real number, so +inf is greater than zero.
It should also be clear that +inf and -inf are not at all equivalent. Besides, if they were equivalent, shouldn't 2-inf equal 2+inf? Yet they don't equal each other (2-inf=0, 2+inf=+inf), so it's inaccurate and misleading to say that +inf and -inf are equivalent.
Now, for 1/0 specifically, IEEE 754 chose to define that +r/+0 and -r/-0 (where +r and -r are any positive or negative real number, respectively) are +inf, and +r/-0 and -r/+0 are -inf. Those operations also raise a "divide by zero" signal. IEEE 754 has both positive and negative zero (they're equal) which is why there are four different cases of dividing a real by zero.
Also in IEEE 754, the only value that cannot be compared with any value is a nan (not-a-number). A nan is usually the result of an undefined operation, such as 0/0 or inf/inf (regardless of the sign). A nan is even unequal to itself.