From: Gelinas, B. <Bruno.Gelinas@CMCElectronics.ca> - 2007-06-01 22:45:55
|
> I have tried option "-fwrapv" in my AdaCore GNAT Programming Studio, = which is suppository using public domain C and C++ compiler from MinGW = (release=3D 3.4.2 mingw-special), and then re-built the entire project. >=20 > However, the following expression is still being capped, not wrapped: >=20 > oibrg =3D (T_180B15_ANGLE)(olv_realbrg * C_RADIAN_TO_B15); >=20 > with olv_realbrg =3D 5.23598775598 rad (or 300deg), oibrg =3D -32768, = instead of expected -10923. >=20 > Where: > #define C_RADIAN_TO_B15 10430.37835047F > typedef T_SIGNED_16 T_180B15_ANGLE; >=20 >=20 > Is there another compiler option to try , or another option I should = be enabling in AdaCore GNAT Programming Studio ? >=20 >=20 > -------------------------------------------------------- > Bruno G=E9linas > Ing=E9nieur logiciel >=20 >=20 |
From: Brian D. <br...@de...> - 2007-06-02 00:38:20
|
"Gelinas, Bruno" wrote: Please don't send your message as quoted text. It appears as if you have nothing to say. > > I have tried option "-fwrapv" in my AdaCore GNAT Programming Studio, which is suppository using public domain C and C++ compiler from MinGW (release= 3.4.2 mingw-special), and then re-built the entire project. First of all, gcc is not public domain. It is licensed under the GPL. There is a huge difference. Parts of MinGW are public domain, but not gcc. > > However, the following expression is still being capped, not wrapped: > > > > oibrg = (T_180B15_ANGLE)(olv_realbrg * C_RADIAN_TO_B15); > > > > with olv_realbrg = 5.23598775598 rad (or 300deg), oibrg = -32768, instead of expected -10923. > > > > Where: > > #define C_RADIAN_TO_B15 10430.37835047F > > typedef T_SIGNED_16 T_180B15_ANGLE; > > > > > > Is there another compiler option to try , or another option I should be enabling in AdaCore GNAT Programming Studio ? I think your understanding of -fwrapv is wrong. This is what the manual says: -fwrapv This option instructs the compiler to assume that signed arithmetic overflow of addition, subtraction and multiplication wraps around using twos-complement representation. This flag enables some optimizations and disables other. This option is enabled by default for the Java front-end, as required by the Java language specification. Note that this does not influence what actually happens in the case of signed overflow, only what the compiler's optimizers can assume. The C standard says that signed overflow is undefined behavior. But the x86 architecture (among others) implement wrapping for signed overflow just the same as unsigned overflow, which means from a practical standpoint you can assume that e.g. INT_MAX + 1 = INT_MIN. However, from a compiler optimizer standpoint, you can't assume that if you're obeying the standard, and there are a certain class of optimizations that you can make if you are willing to assume that overflow of a signed int can never happen, since that would be undefined and no well-formed program invoked undefined behavior. This strict interpretation of the C standard [that signed overflow will never happen] goes against traditional C coding practice since the dark ages, and is somewhat counterintuitive for some people. And in fact in gcc 4.2 a new VRP pass was added that used this allowance to do some optimizations that broke real world C code that required signed overflow to happen. There was a lot of head scratching and debating, and the compromize that came as a result of it was the -Wstrict-overflow and -fstrict-overflow pair of options. This is one of those things, like strict aliasing, that the compiler is allowed by the standard to do, but that many humans don't know about or even disagree about. -fwrapv is a way to tell the compiler "never assume -- even though the standard allows you to -- that signed overflow will never happen in my program, even if that means you can't do some optimizations that you'd otherwise be able to do." But what this flag does not do is tell the compiler whether signed overflow saturates or wraps; that is a function of the hardware and gcc does not have a flag to control it. Now as to your actual problem, I think it's just a matter of missing a cast. But we can't really say anything without a testcase that compiles. I tried: #include <stdio.h> #include <stdint.h> int main() { int16_t foo = (int)(5.23598775598F * 10430.37835047F); printf ("%hd", foo); } ...but this prints -10923. If you remove the (int), then you get 32767, which is probably a result of trying to cast a float to a short without the intermediate int representation. I think that just means you need the cast, there's no flag that will influence this. Brian |