Skip to content

Latest commit

 

History

History

lnum-514

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
==============
  LNUM PATCH
==============

Copyright (c) 2006-08, Asko Kauppi <akauppi@gmail.com>

The LNUM patch, also known as "integer patch" allows Lua 5.1 to treat pure
integer operations with full accuracy and more speed on non-FP platforms,
without changing the external interfaces.

Lua's internal number mode can be easily set to a combination of any of the 
following:

Floating point values ('lua_Number'):

  LNUM_DOUBLE (default)         double precision FP (52 bit mantissa)
  LNUM_FLOAT                    single precision FP (23 bit mantissa)
  LNUM_LDOUBLE                  extra precision FP (80+ bit mantissa, varies)

Integer values ('lua_Integer'):

  LNUM_INT32                    -2^31..2^31-1 integer optimized
  LNUM_INT64                    -2^63..2^63-1 integer optimized

Complex numbers (together with any of the above):

  LNUM_COMPLEX                  Complex (a+bi) number mode (needs C99)

One shall combine these defines, i.e. LNUM_DOUBLE and LNUM_INT64 gives normal
Lua range, with signed 64-bit integer accuracy. The number mode used shall be
written into the 'luaconf.h' file so that it remains consistent for applications
using Lua.

With complex numbers, the general number type gives type for both real and
imaginary components. Integer number type will be applied for scalar integers.


  Implications of using the patch
===================================

Using the patch does NOT change Lua's external behaviour in any way, only 
numerical accuracy is enhanced (depends on modes selected). On non-FPU platforms
a performance boost of around 30% can be expected, depending on the application
in question (for loops and integer table references will see most benefits). 
On FPU platforms, performance should remain the same as a non-patched Lua's.
See attached performance results for real world results.


  Changes in LNUM2 revise
===========================

Since LNUM2, results of FP operations (where one or all parameters are FP) are
no longer checked for producing an integer result. The result is stored in the
FP part of a Lua value, which may in certain configurations (double+int64,
float+int32/64) cause accuracy loss. 

Example:
    a= 2.5
    b= a*a  -- FP result, gets stored as FP even though value is 5
    ...
    b= b+1  -- still FP since 'b' is FP

Normally, this does not matter. Typically operations are dealing with either
floats or integers, and hardly ever need to bring things back to high accuracy
mode. Also, using configuration s.a. 'double+int32' (the default) this whole
issue is not there, since 'double' is able to carry any integer value anyways.

The FP conversion may happen via integer operations, too:

    a= 5
    b= a/2  -- 2.5 is FP
    c= b*2  -- 5.0 still FP
    d= tonumber(c)  - 5 stored as integer

Note that 'c' and 'd' are equal numbers above, although they are internally
stored differently. If one needs to ensure a value is stored (back) as integer,
this can be done via 'tonumber()' as shown.


  Use of unsigned 32/64-bit integers
======================================

Even though the optimized (bit accurate) integer range is signed, using 
hexadecimal notation for the values, they will behave as unsigned 0 .. 
0x[ffffffff]ffffffff range. Care has to be applied, though, and no arithmetic
applied on the values; they are stored as signed values internally.

To output the values, use 'string.format('%x',v)'.


  Use with -ffast-math flag
=============================

LNUM patch tries to make use of gcc '-ffast-math' (or other non-IEEE floating
point math) seamless for Lua users. Plain Lua would have issues with it, i.e.
in dealing with NaN. Grep '__FAST_MATH__' to see the affected places.

'-ffast-math' improves performance on x86 platform essentially (around 10%).
Intel C++ compiler is said to have it on by default.


  Platform notes: Windows
===========================

The Visual C++ 2008 Express development environment does not have full support
for number modes other than LNUM_DOUBLE. What they lack is 'strtof()' and
'strtold()' functions, or equivalents.

Users wishing to use LNUM_LDOUBLE should either compile using 'MinGW' or 
provide their own 'strtold()' function.


  Additions to Lua VM and Lua/C API
=====================================

- integer constant VM instruction

This allows integer constants within a Lua script not to lose accuracy,
regardless of the FP number mode used.

- '_LNUM' global that carries the number mode as a string:
"[complex] double|float|ldouble [int32|int64]"
    
This is mostly for testing purposes, normally an application would not care
to check what the number mode is (or, it can be checked as numerical expressions,
but that is a bit tricky).

The same string is also appeneded to the Lua "opening screen" printout,
alongside version, copyright etc.

- 'lua_isinteger()' addition to the API

To accompany 'lua_tointeger()' already in the API (Lua 5.1).

- 'lua_tocomplex()', 'lua_iscomplex()' and 'luaL_checkcomplex()' consistent
with the number and integer counterparts (only available with LNUM_COMPLEX,
of course).

- 'file:read()' has a new mode "i" for reading in integers. Reading as "n" is
still valid, but may cause accuracy issues (floating point accuracy used).

- Following C99 complex functions added to 'math' namespace:

    complex= math.acosh()
    complex= math.asinh()
    complex= math.atanh()
    scalar= math.arg()
    scalar= math.imag(c)
    scalar= math.real(c)
    complex= math.conj(c)
    complex= math.proj(c)

Note that using LNUM_COMPLEX does _not_ break Lua API that uses 'lua_Number'. 
It remains a scalar, and thus existing Lua modules should be usable also with
Complex internal number mode (of course, as long as imaginary numbers are not
fed to such modules, which will cause an error).

The LNUM_COMPLEX code relies exclusively on the C99 <complex.h> implementation
of complex numbers. Thus, in order to use LNUM_COMPLEX, also enable C99 mode
(i.e. '--std=c99' in gcc).

- 'math.hugeint' giving the largest accurately stored integer value

- '0x...' number constants that are larger than 'lua_Integer' range are NOT
read in as floating point values. Unpatched Lua does so, at least on some
platforms (really depends on the underlying 'strtod()' implementation; i.e.
Visual C++ 2008 does not read in '0x...' as a floating point value).


  Use of the patch
====================

  tar xvzf lua-5.1.4
  cd lua-5.1.4/src
  patch < ../../lua-5.1.4-lnum.patch
  cd ..
  make linux / make macosx / your regular Lua make spell :)

This will make a default (double+int32) configuration. To use others, edit
lines in 'luaconf.h' to include:

  #define LNUM_INT64
  #define LNUM_FLOAT / LNUM_LDOUBLE
  #define LNUM_COMPLEX


  Remake of the patch (for developers)
========================================

  make diff PATCH=xxx.patch


-- AKa 9-Jan-2007 (started 26.8.2006) (updated 13 Aug 2007) (updated 1-2 Oct 2007)
                    (updated 28 Feb 2008) (added 23 Apr 2008)