Hey guys I have found an interesting bug with the cross compiler from
Technologics. If you cast between double/"long long" (in either direction) it
produces crazy results. If I had to guess I would say that it was just doing a
"reinterpret cast" and not actually modifying the data at all. I have a simple
test case that shows the behavior but I need help testing it with recent
versions of the cross compiler so I can know if this is an issue that has
already been addressed by the compiler folks. What I really need is this test
case compiled and run on ts boards so we can see if this occurs on all the
technologic devices/ all the cross compiler versions/ maybe the kernel version.
Also optimization levels appear to affect how the bug manifests, with -03 it
appears it uses the last value that it was compared against.
I can tell you that this bug crops up with the following configuration:
compiler: gcc-3.3.4-glibc-2.3.2
uname: Linux proto2 2.4.26-ts11 #22 Tue Jun 6 12:23:09 MST 2006
device: ts-7250
Output:
$ ./arm.exe
Failure: double->int_64_t doesn't cast correctly: 0 != 1003
Failure: int_64_t->double doesn't cast correctly: 1002 != 1004
Failure: int_64_t->double doesn't cast correctly: 1e-05 != 1006
Failure: int_64_t->double doesn't cast correctly: 1011 != 4.29497e+09
Failure: double->int_64_t doesn't cast correctly: 0 != 4294967296
--------------------------- CastingTest.cpp -------------------------
#include <sstream>
#include <iostream>
template <typename T1, typename T2>
T2 TestCast(T1 input){
return static_cast<T2>(input);
}
template <typename T1>
bool IsEqual(T1 a, T1 b){
return a == b;
}
template <>
bool IsEqual(double a, double b){
double diff = a - b;
if(diff < 0) diff = -diff;
return diff <= 1e-5;
}
template <>
bool IsEqual(float a, float b){
float diff = a - b;
if(diff < 0) diff = -diff;
return diff <= 1e-5;
}
#define CHECK_CAST(t1, t2, a, b)\
{t2 amod = TestCast<t1, t2>(a);\
if(!IsEqual<t2>(amod,(b))){\
std::ostringstream oss;
\
oss << (#t1)<< "->" << (#t2) << " doesn't cast
correctly: " << (amod) << " != " << (b); \
std::cout << "Failure: " << oss.str() << std::endl;\
}}
typedef long long int_64_t;
int main(int argc, char* argv[])
{
CHECK_CAST(double,int,1000.0,1000);
CHECK_CAST(double,float,1001.0,1001.0f);
CHECK_CAST(double,long,1002.0,1002);
CHECK_CAST(double,int_64_t,1003.0,1003);
CHECK_CAST(int_64_t,double,1004,1004.0);
CHECK_CAST(double,float,1012.0,1012.0f);
CHECK_CAST(int_64_t,double,1006,1006.0);
CHECK_CAST(int,double,1007,1007.0);
CHECK_CAST(long,double,1008,1008.0);
CHECK_CAST(int,float,1009,1009.0f);
CHECK_CAST(float,int_64_t,1010.0f,1010);
CHECK_CAST(float,int,1011.0f,1011);
CHECK_CAST(int_64_t,double,4294967296LL,4294967296.0);
CHECK_CAST(double,int_64_t,4294967296.0,4294967296LL);
return 0;
}
---------------------------------------------------------------------
/*
Also : A good work around would also be appreciated, the one I am using is far
from optimal:
*/
double SafeCastInt64ToDouble(int_64_t aInput){
#ifdef ARM
long upper = (aInput & 0xFFFFFFFF00000000LL) >> 32;
unsigned long lower = (aInput & 0x00000000FFFFFFFFLL);
//Shift the upper portion back into the correct range ( e1<<e2
becomes e1 * pow(2.0, e2), in our case pow(2,32)=4294967296)
double f1 = upper * 4294967296.0;
double f2 = lower;
double dblVar = f1 + f2;
return dblVar;
#else
return static_cast<double>(aInput);
#endif
}
------------------------------------
Yahoo! Groups Links
<*> To visit your group on the web, go to:
http://groups.yahoo.com/group/ts-7000/
<*> Your email settings:
Individual Email | Traditional
<*> To change settings online go to:
http://groups.yahoo.com/group/ts-7000/join
(Yahoo! ID required)
<*> To change settings via email:
<*> To unsubscribe from this group, send an email to:
<*> Your use of Yahoo! Groups is subject to:
http://docs.yahoo.com/info/terms/
|