Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8344277
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 9, 20262026-06-09T06:18:54+00:00 2026-06-09T06:18:54+00:00

In an update to Autodesk TinkerBox , I’ve come across an unexpected floating point

  • 0

In an update to Autodesk TinkerBox, I’ve come across an unexpected floating point calculation difference between our internal-only development version that runs on Windows and the version that runs on the our final target of iOS (the following info is based on a debug build running on iPad1).

We use Chipmunk for our physics needs. This is by no means likely to be the only calculation with this problem, but it’s a particular one that I was analyzing:

static inline cpFloat
cpvcross(const cpVect &v1, const cpVect &v2)
{
    return v1.x*v2.y - v1.y*v2.x;
}

The particular case I’m looking at has v1 as (0xC0A7BC40 [-5.241729736328125], 0xC0E84C80 [-7.25933837890625]) and v2 as (0x428848FB [68.14253997802734], 0x42BCBE40 [94.37158203125]). I focus on the hex versions of the values since those are the exact values that are the inputs on both platforms, verified by inspecting the memory locations of v1 and v2 on both platforms. For reference, the floating point values in brackets were grabbed from putting the hex values into this site.

On Windows the result is 0xBA15F8E8 [-0.0005720988847315311], and on iOS the result is 0xBA100000 [-0.00054931640625]. Of course the difference is small, but not really when you consider percentage-wise, and it accumulates over time to show deviations in the behavior of the physics. (Please do not suggest using doubles. It slows the game down, of course, and not using doubles is not the issue here. 🙂 )

For reference, this is a debug build on both platforms, and the code compiles as:

Windows

static inline cpFloat
cpvcross(const cpVect &v1, const cpVect &v2)
{
01324790  push        ebp  
01324791  mov         ebp,esp 
01324793  sub         esp,0C4h 
01324799  push        ebx  
0132479A  push        esi  
0132479B  push        edi  
0132479C  lea         edi,[ebp-0C4h] 
013247A2  mov         ecx,31h 
013247A7  mov         eax,0CCCCCCCCh 
013247AC  rep stos    dword ptr es:[edi] 
    return v1.x*v2.y - v1.y*v2.x;
013247AE  mov         eax,dword ptr [v1] 
013247B1  fld         dword ptr [eax] 
013247B3  mov         ecx,dword ptr [v2] 
013247B6  fmul        dword ptr [ecx+4] 
013247B9  mov         edx,dword ptr [v1] 
013247BC  fld         dword ptr [edx+4] 
013247BF  mov         eax,dword ptr [v2] 
013247C2  fmul        dword ptr [eax] 
013247C4  fsubp       st(1),st 
013247C6  fstp        dword ptr [ebp-0C4h] 
013247CC  fld         dword ptr [ebp-0C4h] 
}
013247D2  pop         edi  
013247D3  pop         esi  
013247D4  pop         ebx  
013247D5  mov         esp,ebp 
013247D7  pop         ebp  
013247D8  ret              

iOS

invent`cpvcross at cpVect.h:63:
0x94a8:  sub    sp, sp, #8
0x94ac:  str    r0, [sp, #4]
0x94b0:  str    r1, [sp]
0x94b4:  ldr    r0, [sp, #4]
0x94b8:  vldr   s0, [r1]
0x94bc:  vldr   s1, [r1, #4]
0x94c0:  vldr   s2, [r0]
0x94c4:  vldr   s3, [r0, #4]
0x94c8:  vmul.f32 s1, s2, s1
0x94cc:  vmul.f32 s0, s3, s0
0x94d0:  vsub.f32 s0, s1, s0
0x94d4:  vmov   r0, s0
0x94d8:  add    sp, sp, #8
0x94dc:  bx     lr   

As near as I can tell, those calculations are identical, assuming each instruction is calculating the result of the operands identically. Xcode does not allow me to step over instruction-by-instruction, for some reason (which Visual Studio does allow), so I can’t narrow down which instruction(s) are deviating compared to the Intel FP unit.

So, why is the result of such a simply calculation so different between the two CPUs?

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-09T06:18:56+00:00Added an answer on June 9, 2026 at 6:18 am

    You’re seeing the results of using different floating-point precision for calculations.

    In the x86 code, the calculations are done in the FPU registers which are extended precision (80 bits), while NEON code uses floats (32-bit). Apparently the extra precision during multiplication and subtraction allows x86 code to retain more bits while ARM code loses them.

    Using the _controlfp functions you can tell the FPU to use a specific precision for all calculations. I made a small program using the example from MSDN and was able to get the same result as ARM code:

    #include <stdio.h>
    typedef float cpFloat;
    struct cpVect  {cpFloat x, y;};
    struct cpVectI {unsigned int x, y;};
    union cpv {cpVectI i; cpVect f;};
    union cfi { float f; unsigned int i;};
    
    cpFloat cpvcross(const cpVect &v1, const cpVect &v2)
    {
        return v1.x*v2.y - v1.y*v2.x;
    }
    
    #include <float.h>
    #pragma fenv_access (on)
    
    void main(void)
    {
      cpv v1, v2;
      cfi fi;
      v1.i.x = 0xC0A7BC40;
      v1.i.y = 0xC0E84C80;
      v2.i.x = 0x428848FB;
      v2.i.y = 0x42BCBE40;
    
      unsigned int control_word_x87;
    
      // Show original x87 control word and do calculation.
      __control87_2(0, 0, &control_word_x87, 0);
      printf( "Original: 0x%.4x\n", control_word_x87 );
      fi.f = cpvcross(v1.f, v2.f);
      printf("Result: %g (0x%08X)\n", fi.f, fi.i);
    
      // Set precision to 24 bits and recalculate.
      __control87_2(_PC_24, MCW_PC, &control_word_x87, 0);
      printf( "24-bit:   0x%.4x\n", control_word_x87);
      fi.f = cpvcross(v1.f, v2.f);
      printf("Result: %g (0x%08X)\n", fi.f, fi.i);
    
      // Restore default precision-control bits and recalculate.
      __control87_2( _CW_DEFAULT, MCW_PC, &control_word_x87, 0);
      printf( "Default:  0x%.4x\n", control_word_x87 );
      fi.f = cpvcross(v1.f, v2.f);
      printf("Result: %g (0x%08X)\n", fi.f, fi.i);
    }
    

    Here’s the output:

    Original: 0x9001f
    Result: -0.000572099 (0xBA15F8E8)
    24-bit:   0xa001f
    Result: -0.000549316 (0xBA100000)
    Default:  0x9001f
    Result: -0.000572099 (0xBA15F8E8)
    

    Be careful when using this function and calling external libraries; some code might be relying on the default settings and will break if you change them behind its back.

    Another option could be to switch to SSE intrinsics which will use a specific precision. Unfortunately, /arch:SSE2 doesn’t seem to make use of SSE2 for floating point (at least in VS2010).

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

Update: Is there a way to achieve what I'm trying to do in an
update: I mistyped 2 variables...so embarrassing. thanks everyone for the effort! sorry i find
Update: I reported this as a bug to Apple and they fixed it! All
UPDATE: I've been playing around with this more, and it seems like tmux's clear-history
Update : This is no longer an issue from C# 6, which has introduced
UPDATE UPI_ATTRIBUTE SET SITE_INC ='0' WHERE USER_PROFILING_NAME IN ('CAR_IMPLICIT','CAR_EXPLICIT') Above is my query that
Update: Switching to IIS Express instead of the Visual Studio Development Server fixed the
UPDATE 6/21/12 I have a form in rails that is working similar to an
Update : I found almost exact similar question , yet it has slightly different
UPDATE: I'm getting this error: (No route matches /docs/index.html... ) when accessing admin.example.com/docs/index.html The

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.