Elminate loadstring. Do parsing manually in complex.to.
String syntax has changed slightly. Suggested by Satheesh.master
parent
58790b6b7c
commit
8dd7aa293f
|
@ -1,5 +1,9 @@
|
|||
complex changelog
|
||||
|
||||
v 0.3.3: 2011-12-13
|
||||
- Elminate loadstring. Do parsing manually in complex.to.
|
||||
String syntax has changed slightly.
|
||||
|
||||
v 0.3.2: 2011-12-03
|
||||
- Add _VERSION
|
||||
|
||||
|
|
108
lua/complex.lua
108
lua/complex.lua
|
@ -59,16 +59,61 @@ DOWNLOAD/INSTALL
|
|||
--/////////////--
|
||||
|
||||
-- link to complex table
|
||||
local complex = {_TYPE='module', _NAME='complex', _VERSION='0.3.2.20111203'}
|
||||
local complex = {_TYPE='module', _NAME='complex', _VERSION='0.3.3.20111212'}
|
||||
|
||||
-- link to complex metatable
|
||||
local complex_meta = {}
|
||||
|
||||
-- helper functions for parsing complex number strings.
|
||||
local function parse_scalar(s, pos0)
|
||||
local x, n, pos = s:match('^([+-]?[%d%.]+)(.?)()', pos0)
|
||||
if not x then return end
|
||||
if n == 'e' or n == 'E' then
|
||||
local x2, n2, pos2 = s:match('^([+-]?%d+)(.?)()', pos)
|
||||
if not x2 then error 'number format error' end
|
||||
x = tonumber(x..n..x2)
|
||||
if not x then error 'number format error' end
|
||||
return x, n2, pos2
|
||||
else
|
||||
x = tonumber(x)
|
||||
if not x then error 'number format error' end
|
||||
return x, n, pos
|
||||
end
|
||||
end
|
||||
local function parse_component(s, pos0)
|
||||
local x, n, pos = parse_scalar(s, pos0)
|
||||
if not x then
|
||||
local x2, n2, pos2 = s:match('^([+-]?)(i)()$', pos0)
|
||||
if not x2 then error 'number format error' end
|
||||
return (x2=='-' and -1 or 1), n2, pos2
|
||||
end
|
||||
if n == '/' then
|
||||
local x2, n2, pos2 = parse_scalar(s, pos)
|
||||
x = x / x2
|
||||
return x, n2, pos2
|
||||
end
|
||||
return x, n, pos
|
||||
end
|
||||
local function parse_complex(s)
|
||||
local x, n, pos = parse_component(s, 1)
|
||||
if n == '+' or n == '-' then
|
||||
local x2, n2, pos2 = parse_component(s, pos)
|
||||
if n2 ~= 'i' or pos2 ~= #s+1 then error 'number format error' end
|
||||
if n == '-' then x2 = - x2 end
|
||||
return x, x2
|
||||
elseif n == '' then
|
||||
return x, 0
|
||||
elseif n == 'i' then
|
||||
if pos ~= #s+1 then error 'number format error' end
|
||||
return 0, x
|
||||
else
|
||||
error 'number format error'
|
||||
end
|
||||
end
|
||||
|
||||
-- complex.to( arg )
|
||||
-- return a complex number on success
|
||||
-- return nil on failure
|
||||
local _retone = function() return 1 end
|
||||
local _retminusone = function() return -1 end
|
||||
function complex.to( num )
|
||||
-- check for table type
|
||||
if type( num ) == "table" then
|
||||
|
@ -88,55 +133,8 @@ function complex.to( num )
|
|||
return setmetatable( { isnum,0 }, complex_meta )
|
||||
end
|
||||
if type( num ) == "string" then
|
||||
-- check for real and complex
|
||||
-- number chars [%-%+%*%^%d%./Ee]
|
||||
local real,sign,imag = string.match( num, "^([%-%+%*%^%d%./Ee]*%d)([%+%-])([%-%+%*%^%d%./Ee]*)i$" )
|
||||
if real then
|
||||
if string.lower(string.sub(real,1,1)) == "e"
|
||||
or string.lower(string.sub(imag,1,1)) == "e" then
|
||||
return
|
||||
end
|
||||
if imag == "" then
|
||||
if sign == "+" then
|
||||
imag = _retone
|
||||
else
|
||||
imag = _retminusone
|
||||
end
|
||||
elseif sign == "+" then
|
||||
imag = loadstring("return tonumber("..imag..")")
|
||||
else
|
||||
imag = loadstring("return tonumber("..sign..imag..")")
|
||||
end
|
||||
real = loadstring("return tonumber("..real..")")
|
||||
if real and imag then
|
||||
return setmetatable( { real(),imag() }, complex_meta )
|
||||
end
|
||||
return
|
||||
end
|
||||
-- check for complex
|
||||
local imag = string.match( num,"^([%-%+%*%^%d%./Ee]*)i$" )
|
||||
if imag then
|
||||
if imag == "" then
|
||||
return setmetatable( { 0,1 }, complex_meta )
|
||||
elseif imag == "-" then
|
||||
return setmetatable( { 0,-1 }, complex_meta )
|
||||
end
|
||||
if string.lower(string.sub(imag,1,1)) ~= "e" then
|
||||
imag = loadstring("return tonumber("..imag..")")
|
||||
if imag then
|
||||
return setmetatable( { 0,imag() }, complex_meta )
|
||||
end
|
||||
end
|
||||
return
|
||||
end
|
||||
-- should be real
|
||||
local real = string.match( num,"^(%-*[%d%.][%-%+%*%^%d%./Ee]*)$" )
|
||||
if real then
|
||||
real = loadstring( "return tonumber("..real..")" )
|
||||
if real then
|
||||
return setmetatable( { real(),0 }, complex_meta )
|
||||
end
|
||||
end
|
||||
local real, imag = parse_complex(num)
|
||||
return setmetatable( { real, imag }, complex_meta )
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -170,7 +168,7 @@ end
|
|||
-- complex.convpolardeg( r, phi )
|
||||
-- convert polar coordinates ( r*e^(i*phi) ) to carthesic complex number
|
||||
-- r (radius) is a number
|
||||
-- phi must be in degrees; e.g. [0° - 360°]
|
||||
-- phi must be in degrees; e.g. [0 - 360 deg]
|
||||
function complex.convpolardeg( radius, phi )
|
||||
phi = phi/180 * math.pi
|
||||
return setmetatable( { radius * math.cos( phi ), radius * math.sin( phi ) }, complex_meta )
|
||||
|
@ -219,7 +217,7 @@ end
|
|||
|
||||
-- complex.polardeg( cx )
|
||||
-- from complex number to polar coordinates
|
||||
-- output in degrees; [-180°,180°]
|
||||
-- output in degrees; [-180, 180 deg]
|
||||
-- returns r (radius), phi (angle)
|
||||
function complex.polardeg( cx )
|
||||
return math.sqrt( cx[1]^2 + cx[2]^2 ), math.atan2( cx[2], cx[1] ) / math.pi * 180
|
||||
|
@ -421,4 +419,4 @@ return complex
|
|||
|
||||
--///////////////--
|
||||
--// chillcode //--
|
||||
--///////////////--
|
||||
--///////////////--
|
||||
|
|
|
@ -8,16 +8,35 @@ assert( tostring( cx ) == "2+3i" )
|
|||
cx = complex ( 2 )
|
||||
assert( tostring( cx ) == "2" )
|
||||
assert( cx:tostring() == 2 )
|
||||
cx = complex "2^2+3/2i"
|
||||
assert( tostring( cx ) == "4+1.5i" )
|
||||
cx = complex ".5-2E-3i"
|
||||
assert( tostring( cx ) == "0.5-0.002i" )
|
||||
cx = complex "3i"
|
||||
assert( tostring( cx ) == "3i" )
|
||||
--old:no longer supported: assert( tostring(complex '2^2+3/2i') == '4+1.5i' )
|
||||
assert( tostring( complex '.5-2E-3i' ) == '0.5-0.002i' )
|
||||
assert( tostring( complex '0' ) == '0' )
|
||||
assert( tostring( complex '10' ) == '10' )
|
||||
assert( tostring( complex '10.2' ) == '10.2' )
|
||||
assert( tostring( complex '-10.2' ) == '-10.2' )
|
||||
assert( tostring( complex '-10.2e2' ) == '-1020' )
|
||||
assert( tostring( complex '-10.2E+02' ) == '-1020' )
|
||||
assert( tostring( complex 'i' ) == 'i' )
|
||||
assert( tostring( complex '-i' ) == '-i' )
|
||||
assert( tostring( complex '3i' ) == '3i' )
|
||||
assert( tostring( complex '-3i' ) == '-3i' )
|
||||
assert( tostring( complex '0-3i' ) == '-3i' )
|
||||
assert( tostring( complex '1/+2+3/-4i' ) == '0.5-0.75i' )
|
||||
assert( tostring( complex '1e+0/2.0-1e0/2.0i' ) == '0.5-0.5i' )
|
||||
-- bad formatting
|
||||
assert( not pcall(complex, '') )
|
||||
assert( not pcall(complex, '2 + 4i') ) -- space
|
||||
assert( not pcall(complex, '1+2i ') ) -- space
|
||||
assert( not pcall(complex, 'i+1') ) -- reversed
|
||||
assert( tostring(complex'2 ') == '2' ) --ok (space, not invoking tonumber directly)
|
||||
assert( not pcall(complex, '-') )
|
||||
assert( not pcall(complex, '++1') )
|
||||
assert( not pcall(complex, '1/2/3') ) -- multiple operations
|
||||
|
||||
--
|
||||
cx = complex "2"
|
||||
assert( tostring( cx ) == "2" )
|
||||
assert( cx:tostring() == 2 )
|
||||
assert( complex "2 + 4i" == nil )
|
||||
|
||||
-- complex.new
|
||||
cx = complex.new( 2,3 )
|
||||
|
|
Loading…
Reference in New Issue