-C Attempt\sto\swork\saround\sa\sbug\sin\sthe\sBorland\sBCC\s5.5.1\scompiler.\s\sTicket\s#2880.\s(CVS\s4705)
-D 2008-01-11T00:06:11
+C Do\sexplicit\srange\stests\sbefore\sattempting\sto\sconvert\sa\s64-bit\sfloat\ninto\sa\s64-bit\sinteger.\s\sSome\ssystems\s(windows)\sseem\sto\sthrow\sexceptions\nif\sthe\sconversion\sis\sout\sof\srange.\s\sTicket\s#2880.\s(CVS\s4706)
+D 2008-01-11T15:27:03
F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7
F Makefile.in 30789bf70614bad659351660d76b8e533f3340e9
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
F src/vdbeaux.c db33a4c2477546da05e772352be43896d24d51d5
F src/vdbeblob.c e386d49d8354aa5a58f0a7f2794303442c149120
F src/vdbefifo.c 334c838c8f42d61a94813d136019ee566b5dc2f6
-F src/vdbemem.c 3da7f7fa7f2ab06a5cbaff132898b07e4d095220
+F src/vdbemem.c a86119b5ccc41ab8653e4746f83d591ff0ae892e
F src/vtab.c 03014b2bfa8096ecac5fcdc80d34cd76e06af52a
F src/where.c 9705df3c2b78ea8e02a768be8ac5d3f7a2902f1e
F tclinstaller.tcl 4356d9d94d2b5ed5e68f9f0c80c4df3048dd7617
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
-P 8cbd46517f407b3b1ce187b623db10f00aa415ea
-R 911083b5c48b851385eee47775792145
+P 6de0ee49073c7a47d5e10495b569b33df76d1448
+R 72b005345d91bd390788cc14572cdea6
U drh
-Z ec1836639b43428a4a6ed94e2aced93a
+Z f60ae65829aa8eb88bba7196814bec78
}
}
+/*
+** Convert a 64-bit IEEE double into a 64-bit signed integer.
+** If the double is too large, return 0x8000000000000000.
+**
+** Most systems appear to do this simply by assigning
+** variables and without the extra range tests. But
+** there are reports that windows throws an expection
+** if the floating point value is out of range. (See ticket #2880.)
+** Because we do not completely understand the problem, we will
+** take the conservative approach and always do range tests
+** before attempting the conversion.
+*/
+static i64 doubleToInt64(double r){
+ /*
+ ** Many compilers we encounter do not define constants for the
+ ** minimum and maximum 64-bit integers, or they define them
+ ** inconsistently. And many do not understand the "LL" notation.
+ ** So we define our own static constants here using nothing
+ ** larger than a 32-bit integer constant.
+ */
+ static const i64 maxInt = (((i64)0x7fffffff)<<32)|0xffffffff;
+ static const i64 minInt = ((i64)0x80000000)<<32;
+
+ if( r<(double)minInt ){
+ return minInt;
+ }else if( r>(double)maxInt ){
+ return minInt;
+ }else{
+ return (i64)r;
+ }
+}
+
/*
** Return some kind of integer value which is the best we can do
** at representing the value that *pMem describes as an integer.
if( flags & MEM_Int ){
return pMem->u.i;
}else if( flags & MEM_Real ){
- return (i64)pMem->r;
+ return doubleToInt64(pMem->r);
}else if( flags & (MEM_Str|MEM_Blob) ){
i64 value;
pMem->flags |= MEM_Str;
assert( pMem->flags & MEM_Real );
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
- /* It is reported (in ticket #2880) that the BCC 5.5.1 compiler
- ** will corrupt a floating point number on the right-hand side
- ** of an assignment if the lvalue for the assignment is an integer.
- **
- ** We will attempt to work around this bug in the Borland compiler
- ** by moving the value into a temporary variable first so that if
- ** the assignment into the integer really does corrupt the right-hand
- ** side value, it will corrupt a temporary variable that we do not
- ** care about.
- */
-#ifdef __BORLANDC__
- {
- double r = pMem->r;
- pMem->u.i = r;
- }
-#else
- pMem->u.i = pMem->r;
-#endif
-
- if( ((double)pMem->u.i)==pMem->r ){
+ pMem->u.i = doubleToInt64(pMem->r);
+ if( pMem->r==(double)pMem->u.i ){
pMem->flags |= MEM_Int;
}
}
assert( (pMem->flags & (MEM_Blob|MEM_Str))!=0 );
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
r1 = sqlite3VdbeRealValue(pMem);
- i = (i64)r1;
+ i = doubleToInt64(r1);
r2 = (double)i;
if( r1==r2 ){
sqlite3VdbeMemIntegerify(pMem);