14

When I run the below C++ program in a 32-bit powerpc kernel which supports software floating emulation (hardware floating point disabled), I get a incorrect conditional evaluation. Can some tell me what's the potential problem here?

#include <stdio.h>

int main() {
   int newmax = 1;
   if ((newmax + 0.0) > 256) {
       printf("\nShouldn't be here\n");
   } else {
       printf("\nShould be here\n");
   }
}

Compile:

powerpc-linux-g++ -msoft-float -c floating.cxx
powerpc-linux-g++  -o floating floating.o

Output in target system:

[linux:/]$ ./floating
Shouldn't be here
ST3
  • 8,826
  • 3
  • 68
  • 92
rajachan
  • 795
  • 1
  • 6
  • 20
  • Can you tell me what kernel is that? my best guess is that its emulation do not obey the floating point standard somehow, having a inexact representation of zero. Also, keep in mind that 0.0 defaults to double, not to float. Maybe your software emulator don't support double. – speeder Feb 23 '13 at 20:42
  • 2
    You should specify -msoft-float also when linking. – Marc Glisse Feb 23 '13 at 20:43
  • @speeder. This is a custom 2.6.32.59 kernel. I too doubt this could be a software emulation issue in kernel. – rajachan Feb 23 '13 at 20:46
  • @Marc. -msoft-float also when linking doesn't help. – rajachan Feb 23 '13 at 20:47
  • Kernel of what? linux? BSD? unix? something else? who made it become custom? also did you tried putting a 0.0f or 0.0d and manual casts to test it, just to make sure it is not a automatic conversion issue? – speeder Feb 23 '13 at 20:52
  • @speeder. This is a linux kernel. Just checked and explicit casting doesn't help either. – rajachan Feb 23 '13 at 21:06
  • 1
    Are you sure you are recompiling the correct source code? Change the `printf` error string to be sure! – ouah Feb 23 '13 at 21:11
  • 7
    What if you make all your variables floats to start with? Or doubles? Try narrowing it down to whether it's a casting or an arithmetic error. Print the result of `newmax +0.0` instead of sentences. In my opinion, this question lacks some research of your own. – us2012 Feb 23 '13 at 21:16
  • 1
    FWIW I can't reproduce any of this with a wide array of compilers, target CPU's, flags (--fast-math, O0-4) on GCC or Clang – sehe Feb 23 '13 at 21:21
  • 2
    I am still guessing that your kernel or your compiler is broken, it is not the code. – speeder Feb 23 '13 at 21:25
  • 1
    I can't believe anything _this_ basic is broken in your C implementation. Exact versions of everything involved (Linux distribution, GCC, libc, ...)? Can you print out the value of `newmax + 0.0`? – vonbrand Feb 24 '13 at 01:47
  • That's probably as compiler bug. What's the output of `powerpc-linux-g++ -v` ? – Ottavio Campana Feb 25 '13 at 09:57
  • 6
    Agree with tc. Give us a dissassembly with the -S flag: powerpc-linux-g++ -msoft-float -c floating.cxx -S -o floating.s – Dougvj Mar 08 '13 at 17:05
  • 4
    I think this is a byte-ordering bug. The floating point emulation may have been written for the default big-endian mode of the PPC, but the PPC has been switched to little-endian mode here. – OregonTrail Mar 08 '13 at 23:02
  • *Can some tell me what's the **potential** problem here?* Cosmic ray flipped a bit. – ta.speot.is Mar 09 '13 at 00:45
  • Agree with @ouah. Make sure your changes to the code are getting compiled in. – japreiss Mar 09 '13 at 02:34
  • Comparing floats to ints is generally a bad idea. Read more at http://stackoverflow.com/questions/1161199/is-relational-comparison-between-int-and-float-directly-possible-in-c – Andreas May 22 '13 at 05:35
  • As I am not having the testing environment, First you get the result of int newmax = 1; int val = (newmax + 0.0); float val1 = (newmax + 0.0); after getting the result we can guess the problem over there. –  May 27 '13 at 11:33
  • @mrt, comparing floats to ints is a very reasonable thing to do in many situations. The fact that it doesn't work here means that the implementation is seriously broken (or that the OP is not running the code that we see here). – TonyK Jun 06 '13 at 06:47
  • 2
    @tc: Is that really worth a downvote? You don't need assembler knowledge just because you write floating point code, so at max, you should _suggest_ to include disassembly, but a downvote based on just that is uncalled for. – Sebastian Mach Jun 12 '13 at 06:54

4 Answers4

1

You should specify -msoft-float also when linking Give us a dissassembly with the -S flag: powerpc-linux-g++ -msoft-float -c floating.cxx -S -o floating.s

0

First, why hardware floating point is disabled?

Because of this type casts may be performed in incorrect order.

(double)1 = 0x3FF0000000000000
(float) 1 = 0x3F800000

This is your condition.

if ((newmax + 0.0) > 256)

In your case: 1) newmax casting to float or double; 2) adding 0.0; 3) gotten value casting back to int.

It depends on your machine, but int usually is 32-bit value. To check it you can use:

int i;
printf("%d", sizeof(i));

Anyway, going back to your problem, after calculated value converting into int you get big positive number. In your situation I would print it/or compare not with 0x100 but with

0x3F800000, 0x3FF0000000000000, 0x3FF00000

To find out, what happened, but disassembling is the best option.

Probably it wasn't so helpfull, but that was just my idea, what happened.

ST3
  • 8,826
  • 3
  • 68
  • 92
  • The order in which type casts are performed is specified by the C++ standard. It doesn't care whether floating point operations are done by SW or HW or a mix thereof. – MSalters Jun 25 '13 at 08:19
0

This could be anything from compiler error to assembler error to linker error to kernel error. As other people already pointed out: Compiler errors - which is the most likely source of this error - could be verified (or ruled out), if you provided the output of compiling with the -S option. If it is not a compiler error, a kernel error with the floating point emulation would be the next likely source of the problem.

Kai Petzke
  • 2,150
  • 21
  • 29
-1

The statement in your code newmax + 0.0 produces a result in float or double but is compared with an integer value.

thus this error.

Try this out,

int i=1;
printf("%d",(i+0.0));

you get a result 0 everytime no matter what the value of i. Whereas,

int i=1;
printf("%f",(i+0.0));

This produces 1.0000

Radim Köhler
  • 122,561
  • 47
  • 239
  • 335
Mayank
  • 1,364
  • 1
  • 15
  • 29