Intel® C++ Compiler
Support and discussions for creating C++ code that runs on platforms based on Intel® processors.
This community is designed for sharing of public information. Please do not share Intel or third-party confidential information here.

_Quad + __powq strange behaviour



I will be brief. This code:

_Quad x = 1.0 / __powq(0.0001, 2);

double y = x;

givesy a value of 99999999.999999985, while this:

_Quad x = 1.0 / __powq(0.0001q, 2);

double y = x;

(the only difference being the q in the literal) gives the correct, 100000000.00000000, result. Casting 0.0001 to _Quad in the first example doesn't work either. If I use pow (that is, Microsoft's overload, accepting double), instead of __powq, in the first example, it seems to work properly. It is strange also, because:

_Quad foo = __powq(0.0001, 2);

double foobar = foo; // this seems to give a correct result

_Quad x = 1.0 / foo;

double y = x; // not any more

The prototype I am using is:

_Quad __powq(_Quad x, _Quad y);

This is happening on a Windows XP machine, using Visual Studio 2008 SP1 with Intel's C++ Compiler version 11.1.054.

Any insight into what might be happening, why, and how do I fix it? The problem, obviously, is that I don't have a literal there.

0 Kudos
3 Replies
Black Belt
0.0001 is a double constant. Even if cast afterwards to a wider type, it still retains the value rounded to nearest representable double.
I won't try to guess exactly what you want to fix (your own code, or the decisions Microsoft made about supporting only double, or something else).
Yes, 0.0001 IS a double constant. But I can't explain why this works:

double x = 1.0 / pow(0.0001, 2.0);

And this does not:

double y = 1.0 / __powq(0.0001, 2.0);

It seems that double is "precise enough" for this computation to work, because the first example is fine. I would imagine that the problem is in the casting process - 0.0001 double is somehow "wrongly" converted to a not-0.0001 quad.

Anyway, so my question is this: I have a text file which in it has the number 0.0001. I want to read that number into a _Quad, then compute 1.0 / __powq(number, 2) and then write the result back to another text file. Can you explain how do I do that?
Black Belt
As the docs tell you, there is no support in Microsoft rtl for extended or quad precision scanf/printf, and icl adds none. If you wanted to read 0.0001 as 0.00010000000000000000000000000000000, you would have to write in some work-around of your own. For example, you could multiply by 10000 and round to nearest integer (double will work, if you don't overflow; maybe libimf will support rint(), or you can easily write one), then multiply by 0.0001q. This would "clean up" your inputs up to 4 digits after decimal point. You could write your own atoq() if you chose (assuming you don't find one readily available); I would expect it to be quite slow.
You're not going to convince anyone that 0.0001 is "wrongly converted to quad" when you have
( (0.0001 == _Quad(0.0001) ) == 1
You can't expect the compiler to read your mind, or use context look ahead to say "Oh, he's going to use the double as a quad later on; we should replace the double by quad from the beginning." That contextual data typing battle was fought and resolved in Fortran back when C had nothing but double. C still doesn't have _Quad or anything bigger than long double, whose interpretation is left up to the implementor. Switch to linux if you want standardization of long double.
When you use the supplied sprintf(), evidently, your outputs are rounded to double before converting to string; that looks OK, to the extent you have divulged your requirements.