From 6098e06e09e82409710c52eeaefb11395345e194 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Tue, 26 Oct 2010 17:32:19 -0200 Subject: [PATCH] better organization for coercion functions between lua_Number and integer types + IEEE trick to be used in most platforms, by default --- lua.h | 4 +-- luaconf.h | 98 +++++++++++++++++++++++++++++++++++++++---------------- 2 files changed, 71 insertions(+), 31 deletions(-) diff --git a/lua.h b/lua.h index a5b6086c..aab6a4ec 100644 --- a/lua.h +++ b/lua.h @@ -1,5 +1,5 @@ /* -** $Id: lua.h,v 1.274 2010/09/03 14:14:01 roberto Exp roberto $ +** $Id: lua.h,v 1.275 2010/10/25 20:31:11 roberto Exp roberto $ ** Lua - A Scripting Language ** Lua.org, PUC-Rio, Brazil (http://www.lua.org) ** See Copyright Notice at the end of this file @@ -107,7 +107,7 @@ typedef LUA_NUMBER lua_Number; typedef LUA_INTEGER lua_Integer; /* unsigned integer type */ -typedef unsigned LUA_INT32 lua_Unsigned; +typedef LUA_UNSIGNED lua_Unsigned; diff --git a/luaconf.h b/luaconf.h index 1b881475..59ee71af 100644 --- a/luaconf.h +++ b/luaconf.h @@ -1,5 +1,5 @@ /* -** $Id: luaconf.h,v 1.142 2010/07/28 15:51:59 roberto Exp roberto $ +** $Id: luaconf.h,v 1.143 2010/09/07 19:21:39 roberto Exp roberto $ ** Configuration file for Lua ** See Copyright Notice in lua.h */ @@ -438,26 +438,28 @@ */ #define LUA_INTEGER ptrdiff_t +/* +@@ LUA_UNSIGNED is the integral type used by lua_pushunsigned/lua_tounsigned. +** It must have at least 32 bits. +*/ +#define LUA_UNSIGNED unsigned LUA_INT32 + /* @@ lua_number2int is a macro to convert lua_Number to int. @@ lua_number2integer is a macro to convert lua_Number to LUA_INTEGER. -@@ lua_number2uint is a macro to convert a lua_Number to an unsigned -@* LUA_INT32. -@@ lua_uint2number is a macro to convert an unsigned LUA_INT32 -@* to a lua_Number. -** CHANGE them if you know a faster way to convert a lua_Number to -** int (with any rounding method and without throwing errors) in your -** system. In Pentium machines, a naive typecast from double to int -** in C is extremely slow, so any alternative is worth trying. +@@ lua_number2uint is a macro to convert a lua_Number to a LUA_UNSIGNED. +@@ lua_uint2number is a macro to convert a LUA_UNSIGNED to a lua_Number. */ -/* On a Pentium, resort to a trick */ -#if defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) && !defined(__SSE2__) && \ - (defined(__i386) || defined (_M_IX86) || defined(__i386__)) /* { */ +#if defined(LUA_CORE) /* { */ -/* On a Microsoft compiler, use assembler */ -#if defined(_MSC_VER) /* { */ +#if defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) && \ + !defined(LUA_NOIEEE754TRICK) /* { */ + +/* On a Microsoft compiler on a Pentium, use assembler to avoid chashes + with a DirectX idiosyncrasy */ +#if defined(_MSC_VER) && defined(M_IX86) /* { */ #define lua_number2int(i,n) __asm {__asm fld n __asm fistp i} #define lua_number2integer(i,n) lua_number2int(i, n) @@ -465,31 +467,69 @@ {__int64 l; __asm {__asm fld n __asm fistp l} i = (unsigned int)l;} #else /* }{ */ -/* the next trick should work on any Pentium, but sometimes clashes - with a DirectX idiosyncrasy */ +/* the next trick should work on any machine using IEEE754 with + a 32-bit integer type */ -union luai_Cast { double l_d; long l_l; }; -#define lua_number2int(i,n) \ - { volatile union luai_Cast u; u.l_d = (n) + 6755399441055744.0; (i) = u.l_l; } -#define lua_number2integer(i,n) lua_number2int(i, n) -#define lua_number2uint(i,n) lua_number2int(i, n) +union luai_Cast { double l_d; LUA_INT32 l_p[2]; }; + +/* +@@ LUA_IEEEENDIAN is the endianess of doubles in your machine +@@ (0 for little endian, 1 for big endian); if not defined, Lua will +@@ check it dynamically. +*/ + +#if !defined(LUA_IEEEENDIAN) /* { */ +#define LUAI_EXTRAIEEE \ + static const union luai_Cast ieeeendian = {-(33.0 + 6755399441055744.0)}; +#define LUA_IEEEENDIAN (ieeeendian.l_p[1] == 33) +#else +#define LUAI_EXTRAIEEE /* empty */ +#endif /* } */ + +#define lua_number2int32(i,n,t) \ + { LUAI_EXTRAIEEE \ + volatile union luai_Cast u; u.l_d = (n) + 6755399441055744.0; \ + (i) = (t)u.l_p[LUA_IEEEENDIAN]; } + +#define lua_number2int(i,n) lua_number2int32(i, n, int) +#define lua_number2integer(i,n) lua_number2int32(i, n, LUA_INTEGER) +#define lua_number2uint(i,n) lua_number2int32(i, n, LUA_UNSIGNED) #endif /* } */ -#else /* }{ */ -/* this option always works, but may be slow */ -#define lua_number2int(i,n) ((i)=(int)(n)) -#define lua_number2integer(i,n) ((i)=(LUA_INTEGER)(n)) -#define lua_number2uint(i,n) ((i)=(unsigned LUA_INT32)(n)) - #endif /* } */ -/* on several machines, coercion from unsigned to double is too slow, - so avoid that if possible */ +/* the following definitions always work, but may be slow */ + +#if !defined(lua_number2int) +#define lua_number2int(i,n) ((i)=(int)(n)) +#endif + +#if !defined(lua_number2integer) +#define lua_number2integer(i,n) ((i)=(LUA_INTEGER)(n)) +#endif + +#if !defined(lua_number2uint) && (defined(lapi_c) || defined(luaall_c)) /* { */ +/* the following definition assures proper modulo behavior */ +#if defined(LUA_NUMBER_DOUBLE) +#include +#define lua_number2uint(i,n) \ + ((i)=(LUA_UNSIGNED)((n) - floor((n)/4294967296.0)*4294967296.0)) +#else +#define lua_number2uint(i,n) ((i)=(LUA_UNSIGNED)(n)) +#endif +#endif /* } */ + +#if !defined(lua_uint2number) +/* on several machines, coercion from unsigned to double is slow, + so it may be worth to avoid */ #define lua_uint2number(u) \ ((LUA_INT32)(u) < 0 ? (lua_Number)(u) : (lua_Number)(LUA_INT32)(u)) +#endif + +#endif /* } */ /*