ref: 581afbf636745df48c52cae17678259103f7fce5
parent: c8c59b1dfc38561e21a16e97bbf7325e62b1a0e1
author: JeffBezanson <[email protected]>
date: Tue Oct 7 21:14:23 EDT 2008
fixing the result of casting floating point numbers to uint64 handling NULL locale
--- a/femtolisp/unittest.lsp
+++ b/femtolisp/unittest.lsp
@@ -62,6 +62,8 @@
(assert (equal (* 2 #int64(0x4000000000000000))
#uint64(0x8000000000000000)))
+(assert (equal (uint64 (double -123)) #uint64(0xffffffffffffff85)))
+
(assert (equal (string 'sym #char(65) #wchar(945) "blah") "symA\u03B1blah"))
--- a/llt/operators.c
+++ b/llt/operators.c
@@ -89,7 +89,7 @@
if (d > 0 && *(int64_t*)dest < 0) // 0x8000000000000000 is a bitch
*(int64_t*)dest = S64_MAX;
break;
- case T_UINT64: *(uint64_t*)dest = d; break;
+ case T_UINT64: *(uint64_t*)dest = (int64_t)d; break;
case T_FLOAT: *(float*)dest = d; break;
case T_DOUBLE: *(double*)dest = d; break;
}
@@ -115,10 +115,30 @@
}
CONV_TO_INTTYPE(int64)
-CONV_TO_INTTYPE(uint64)
CONV_TO_INTTYPE(int32)
CONV_TO_INTTYPE(uint32)
+// this is needed to work around a possible compiler bug
+// casting negative floats and doubles to uint64. you need
+// to cast to int64 first.
+uint64_t conv_to_uint64(void *data, numerictype_t tag)
+{
+ uint64_t i=0;
+ switch (tag) {
+ case T_INT8: i = (uint64_t)*(int8_t*)data; break;
+ case T_UINT8: i = (uint64_t)*(uint8_t*)data; break;
+ case T_INT16: i = (uint64_t)*(int16_t*)data; break;
+ case T_UINT16: i = (uint64_t)*(uint16_t*)data; break;
+ case T_INT32: i = (uint64_t)*(int32_t*)data; break;
+ case T_UINT32: i = (uint64_t)*(uint32_t*)data; break;
+ case T_INT64: i = (uint64_t)*(int64_t*)data; break;
+ case T_UINT64: i = (uint64_t)*(uint64_t*)data; break;
+ case T_FLOAT: i = (uint64_t)(int64_t)*(float*)data; break;
+ case T_DOUBLE: i = (uint64_t)(int64_t)*(double*)data; break;
+ }
+ return i;
+}
+
int cmp_same_lt(void *a, void *b, numerictype_t tag)
{
switch (tag) {
@@ -226,7 +246,7 @@
return ((int64_t)*(uint64_t*)a == *(int64_t*)b);
}
else if (btag == T_DOUBLE) {
- return (*(uint64_t*)a == (uint64_t)*(double*)b);
+ return (*(uint64_t*)a == (uint64_t)(int64_t)*(double*)b);
}
}
else if (atag == T_INT64) {
@@ -242,7 +262,7 @@
return ((int64_t)*(uint64_t*)b == *(int64_t*)a);
}
else if (atag == T_DOUBLE) {
- return (*(uint64_t*)b == (uint64_t)*(double*)a);
+ return (*(uint64_t*)b == (uint64_t)(int64_t)*(double*)a);
}
}
else if (btag == T_INT64) {
--- a/llt/utf8.c
+++ b/llt/utf8.c
@@ -546,6 +546,8 @@
int u8_is_locale_utf8(const char *locale)
{
+ if (locale == NULL) return 0;
+
/* this code based on libutf8 */
const char* cp = locale;