123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747 |
- --- a/Makefile
- +++ b/Makefile
- @@ -42,7 +42,7 @@
-
- # What to install.
- TO_BIN= lua luac
- -TO_INC= lua.h luaconf.h lualib.h lauxlib.h ../etc/lua.hpp
- +TO_INC= lua.h luaconf.h lualib.h lauxlib.h lnum_config.h ../etc/lua.hpp
- TO_LIB= liblua.a
- TO_MAN= lua.1 luac.1
-
- --- a/src/Makefile
- +++ b/src/Makefile
- @@ -25,7 +25,7 @@ PLATS= aix ansi bsd freebsd generic linu
- LUA_A= liblua.a
- CORE_O= lapi.o lcode.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o lmem.o \
- lobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o ltm.o \
- - lundump.o lvm.o lzio.o
- + lundump.o lvm.o lzio.o lnum.o
- LIB_O= lauxlib.o lbaselib.o ldblib.o liolib.o lmathlib.o loslib.o ltablib.o \
- lstrlib.o loadlib.o linit.o
-
- @@ -148,6 +148,7 @@ llex.o: llex.c lua.h luaconf.h ldo.h lob
- lmathlib.o: lmathlib.c lua.h luaconf.h lauxlib.h lualib.h
- lmem.o: lmem.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h \
- ltm.h lzio.h lmem.h ldo.h
- +lnum.o: lnum.c lua.h llex.h lnum.h
- loadlib.o: loadlib.c lua.h luaconf.h lauxlib.h lualib.h
- lobject.o: lobject.c lua.h luaconf.h ldo.h lobject.h llimits.h lstate.h \
- ltm.h lzio.h lmem.h lstring.h lgc.h lvm.h
- @@ -179,4 +180,18 @@ lzio.o: lzio.c lua.h luaconf.h llimits.h
- print.o: print.c ldebug.h lstate.h lua.h luaconf.h lobject.h llimits.h \
- ltm.h lzio.h lmem.h lopcodes.h lundump.h
-
- +luaconf.h: lnum_config.h
- +lapi.c: lnum.h
- +lauxlib.c: llimits.h
- +lbaselib.c: llimits.h lobject.h lapi.h
- +lcode.c: lnum.h
- +liolib.c: lnum.h llex.h
- +llex.c: lnum.h
- +lnum.h: lobject.h
- +lobject.c: llex.h lnum.h
- +ltable.c: lnum.h
- +lua.c: llimits.h
- +lvm.c: llex.h lnum.h
- +print.c: lnum.h
- +
- # (end of Makefile)
- --- a/src/lapi.c
- +++ b/src/lapi.c
- @@ -28,7 +28,7 @@
- #include "ltm.h"
- #include "lundump.h"
- #include "lvm.h"
- -
- +#include "lnum.h"
-
-
- const char lua_ident[] =
- @@ -241,12 +241,13 @@ LUA_API void lua_pushvalue (lua_State *L
-
- LUA_API int lua_type (lua_State *L, int idx) {
- StkId o = index2adr(L, idx);
- - return (o == luaO_nilobject) ? LUA_TNONE : ttype(o);
- + return (o == luaO_nilobject) ? LUA_TNONE : ttype_ext(o);
- }
-
-
- LUA_API const char *lua_typename (lua_State *L, int t) {
- UNUSED(L);
- + lua_assert( t!= LUA_TINT );
- return (t == LUA_TNONE) ? "no value" : luaT_typenames[t];
- }
-
- @@ -264,6 +265,14 @@ LUA_API int lua_isnumber (lua_State *L,
- }
-
-
- +LUA_API int lua_isinteger (lua_State *L, int idx) {
- + TValue tmp;
- + lua_Integer dum;
- + const TValue *o = index2adr(L, idx);
- + return tonumber(o,&tmp) && (ttisint(o) || tt_integer_valued(o,&dum));
- +}
- +
- +
- LUA_API int lua_isstring (lua_State *L, int idx) {
- int t = lua_type(L, idx);
- return (t == LUA_TSTRING || t == LUA_TNUMBER);
- @@ -309,31 +318,66 @@ LUA_API int lua_lessthan (lua_State *L,
- }
-
-
- -
- LUA_API lua_Number lua_tonumber (lua_State *L, int idx) {
- TValue n;
- const TValue *o = index2adr(L, idx);
- - if (tonumber(o, &n))
- + if (tonumber(o, &n)) {
- +#ifdef LNUM_COMPLEX
- + if (nvalue_img(o) != 0)
- + luaG_runerror(L, "expecting a real number");
- +#endif
- return nvalue(o);
- - else
- - return 0;
- + }
- + return 0;
- }
-
-
- LUA_API lua_Integer lua_tointeger (lua_State *L, int idx) {
- TValue n;
- + /* Lua 5.1 documented behaviour is to return nonzero for non-integer:
- + * "If the number is not an integer, it is truncated in some non-specified way."
- + * I would suggest to change this, to return 0 for anything that would
- + * not fit in 'lua_Integer'.
- + */
- +#ifdef LUA_COMPAT_TOINTEGER
- + /* Lua 5.1 compatible */
- const TValue *o = index2adr(L, idx);
- if (tonumber(o, &n)) {
- - lua_Integer res;
- - lua_Number num = nvalue(o);
- - lua_number2integer(res, num);
- - return res;
- + lua_Integer i;
- + lua_Number d;
- + if (ttisint(o)) return ivalue(o);
- + d= nvalue_fast(o);
- +# ifdef LNUM_COMPLEX
- + if (nvalue_img_fast(o) != 0)
- + luaG_runerror(L, "expecting a real number");
- +# endif
- + lua_number2integer(i, d);
- + return i;
- }
- - else
- - return 0;
- +#else
- + /* New suggestion */
- + const TValue *o = index2adr(L, idx);
- + if (tonumber(o, &n)) {
- + lua_Integer i;
- + if (ttisint(o)) return ivalue(o);
- + if (tt_integer_valued(o,&i)) return i;
- + }
- +#endif
- + return 0;
- }
-
-
- +#ifdef LNUM_COMPLEX
- +LUA_API lua_Complex lua_tocomplex (lua_State *L, int idx) {
- + TValue tmp;
- + const TValue *o = index2adr(L, idx);
- + if (tonumber(o, &tmp))
- + return nvalue_complex(o);
- + return 0;
- +}
- +#endif
- +
- +
- LUA_API int lua_toboolean (lua_State *L, int idx) {
- const TValue *o = index2adr(L, idx);
- return !l_isfalse(o);
- @@ -364,6 +408,7 @@ LUA_API size_t lua_objlen (lua_State *L,
- case LUA_TSTRING: return tsvalue(o)->len;
- case LUA_TUSERDATA: return uvalue(o)->len;
- case LUA_TTABLE: return luaH_getn(hvalue(o));
- + case LUA_TINT:
- case LUA_TNUMBER: {
- size_t l;
- lua_lock(L); /* `luaV_tostring' may create a new string */
- @@ -426,6 +471,8 @@ LUA_API void lua_pushnil (lua_State *L)
- }
-
-
- +/* 'lua_pushnumber()' may lose accuracy on integers, 'lua_pushinteger' will not.
- + */
- LUA_API void lua_pushnumber (lua_State *L, lua_Number n) {
- lua_lock(L);
- setnvalue(L->top, n);
- @@ -434,12 +481,22 @@ LUA_API void lua_pushnumber (lua_State *
- }
-
-
- -LUA_API void lua_pushinteger (lua_State *L, lua_Integer n) {
- +LUA_API void lua_pushinteger (lua_State *L, lua_Integer i) {
- + lua_lock(L);
- + setivalue(L->top, i);
- + api_incr_top(L);
- + lua_unlock(L);
- +}
- +
- +
- +#ifdef LNUM_COMPLEX
- +LUA_API void lua_pushcomplex (lua_State *L, lua_Complex v) {
- lua_lock(L);
- - setnvalue(L->top, cast_num(n));
- + setnvalue_complex( L->top, v );
- api_incr_top(L);
- lua_unlock(L);
- }
- +#endif
-
-
- LUA_API void lua_pushlstring (lua_State *L, const char *s, size_t len) {
- @@ -569,7 +626,7 @@ LUA_API void lua_rawgeti (lua_State *L,
- lua_lock(L);
- o = index2adr(L, idx);
- api_check(L, ttistable(o));
- - setobj2s(L, L->top, luaH_getnum(hvalue(o), n));
- + setobj2s(L, L->top, luaH_getint(hvalue(o), n));
- api_incr_top(L);
- lua_unlock(L);
- }
- @@ -597,6 +654,9 @@ LUA_API int lua_getmetatable (lua_State
- case LUA_TUSERDATA:
- mt = uvalue(obj)->metatable;
- break;
- + case LUA_TINT:
- + mt = G(L)->mt[LUA_TNUMBER];
- + break;
- default:
- mt = G(L)->mt[ttype(obj)];
- break;
- @@ -687,7 +747,7 @@ LUA_API void lua_rawseti (lua_State *L,
- api_checknelems(L, 1);
- o = index2adr(L, idx);
- api_check(L, ttistable(o));
- - setobj2t(L, luaH_setnum(L, hvalue(o), n), L->top-1);
- + setobj2t(L, luaH_setint(L, hvalue(o), n), L->top-1);
- luaC_barriert(L, hvalue(o), L->top-1);
- L->top--;
- lua_unlock(L);
- @@ -721,7 +781,7 @@ LUA_API int lua_setmetatable (lua_State
- break;
- }
- default: {
- - G(L)->mt[ttype(obj)] = mt;
- + G(L)->mt[ttype_ext(obj)] = mt;
- break;
- }
- }
- @@ -1085,3 +1145,32 @@ LUA_API const char *lua_setupvalue (lua_
- return name;
- }
-
- +
- +/* Help function for 'luaB_tonumber()', avoids multiple str->number
- + * conversions for Lua "tonumber()".
- + *
- + * Also pushes floating point numbers with integer value as integer, which
- + * can be used by 'tonumber()' in scripts to bring values back to integer
- + * realm.
- + *
- + * Note: The 'back to integer realm' is _not_ to affect string conversions:
- + * 'tonumber("4294967295.1")' should give a floating point value, although
- + * the value would be 4294967296 (and storable in int64 realm).
- + */
- +int lua_pushvalue_as_number (lua_State *L, int idx)
- +{
- + const TValue *o = index2adr(L, idx);
- + TValue tmp;
- + lua_Integer i;
- + if (ttisnumber(o)) {
- + if ( (!ttisint(o)) && tt_integer_valued(o,&i)) {
- + lua_pushinteger( L, i );
- + return 1;
- + }
- + } else if (!tonumber(o, &tmp)) {
- + return 0;
- + }
- + if (ttisint(o)) lua_pushinteger( L, ivalue(o) );
- + else lua_pushnumber( L, nvalue_fast(o) );
- + return 1;
- +}
- --- a/src/lapi.h
- +++ b/src/lapi.h
- @@ -13,4 +13,6 @@
-
- LUAI_FUNC void luaA_pushobject (lua_State *L, const TValue *o);
-
- +int lua_pushvalue_as_number (lua_State *L, int idx);
- +
- #endif
- --- a/src/lauxlib.c
- +++ b/src/lauxlib.c
- @@ -23,7 +23,7 @@
- #include "lua.h"
-
- #include "lauxlib.h"
- -
- +#include "llimits.h"
-
- #define FREELIST_REF 0 /* free list of references */
-
- @@ -66,7 +66,7 @@ LUALIB_API int luaL_typerror (lua_State
-
-
- static void tag_error (lua_State *L, int narg, int tag) {
- - luaL_typerror(L, narg, lua_typename(L, tag));
- + luaL_typerror(L, narg, tag==LUA_TINT ? "integer" : lua_typename(L, tag));
- }
-
-
- @@ -188,8 +188,8 @@ LUALIB_API lua_Number luaL_optnumber (lu
-
- LUALIB_API lua_Integer luaL_checkinteger (lua_State *L, int narg) {
- lua_Integer d = lua_tointeger(L, narg);
- - if (d == 0 && !lua_isnumber(L, narg)) /* avoid extra test when d is not 0 */
- - tag_error(L, narg, LUA_TNUMBER);
- + if (d == 0 && !lua_isinteger(L, narg)) /* avoid extra test when d is not 0 */
- + tag_error(L, narg, LUA_TINT);
- return d;
- }
-
- @@ -200,6 +200,16 @@ LUALIB_API lua_Integer luaL_optinteger (
- }
-
-
- +#ifdef LNUM_COMPLEX
- +LUALIB_API lua_Complex luaL_checkcomplex (lua_State *L, int narg) {
- + lua_Complex c = lua_tocomplex(L, narg);
- + if (c == 0 && !lua_isnumber(L, narg)) /* avoid extra test when c is not 0 */
- + tag_error(L, narg, LUA_TNUMBER);
- + return c;
- +}
- +#endif
- +
- +
- LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *event) {
- if (!lua_getmetatable(L, obj)) /* no metatable? */
- return 0;
- --- a/src/lauxlib.h
- +++ b/src/lauxlib.h
- @@ -57,6 +57,12 @@ LUALIB_API lua_Number (luaL_optnumber) (
- LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int numArg);
- LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int nArg,
- lua_Integer def);
- +#define luaL_checkint32(L,narg) ((int)luaL_checkinteger(L,narg))
- +#define luaL_optint32(L,narg,def) ((int)luaL_optinteger(L,narg,def))
- +
- +#ifdef LNUM_COMPLEX
- + LUALIB_API lua_Complex (luaL_checkcomplex) (lua_State *L, int narg);
- +#endif
-
- LUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg);
- LUALIB_API void (luaL_checktype) (lua_State *L, int narg, int t);
- --- a/src/lbaselib.c
- +++ b/src/lbaselib.c
- @@ -18,7 +18,9 @@
-
- #include "lauxlib.h"
- #include "lualib.h"
- -
- +#include "llimits.h"
- +#include "lobject.h"
- +#include "lapi.h"
-
-
-
- @@ -54,20 +56,25 @@ static int luaB_tonumber (lua_State *L)
- int base = luaL_optint(L, 2, 10);
- if (base == 10) { /* standard conversion */
- luaL_checkany(L, 1);
- - if (lua_isnumber(L, 1)) {
- - lua_pushnumber(L, lua_tonumber(L, 1));
- + if (lua_isnumber(L, 1)) { /* numeric string, or a number */
- + lua_pushvalue_as_number(L,1); /* API extension (not to lose accuracy here) */
- return 1;
- - }
- + }
- }
- else {
- const char *s1 = luaL_checkstring(L, 1);
- char *s2;
- - unsigned long n;
- + unsigned LUA_INTEGER n;
- luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range");
- - n = strtoul(s1, &s2, base);
- + n = lua_str2ul(s1, &s2, base);
- if (s1 != s2) { /* at least one valid digit? */
- while (isspace((unsigned char)(*s2))) s2++; /* skip trailing spaces */
- if (*s2 == '\0') { /* no invalid trailing characters? */
- +
- + /* Push as number, there needs to be separate 'luaB_tointeger' for
- + * when the caller wants to preserve the bits (matters if unsigned
- + * values are used).
- + */
- lua_pushnumber(L, (lua_Number)n);
- return 1;
- }
- @@ -144,7 +151,7 @@ static int luaB_setfenv (lua_State *L) {
- luaL_checktype(L, 2, LUA_TTABLE);
- getfunc(L, 0);
- lua_pushvalue(L, 2);
- - if (lua_isnumber(L, 1) && lua_tonumber(L, 1) == 0) {
- + if (lua_isnumber(L, 1) && lua_tointeger(L, 1) == 0) {
- /* change environment of current thread */
- lua_pushthread(L);
- lua_insert(L, -2);
- @@ -209,7 +216,7 @@ static int luaB_collectgarbage (lua_Stat
- return 1;
- }
- default: {
- - lua_pushnumber(L, res);
- + lua_pushinteger(L, res);
- return 1;
- }
- }
- @@ -631,6 +638,8 @@ static void base_open (lua_State *L) {
- luaL_register(L, "_G", base_funcs);
- lua_pushliteral(L, LUA_VERSION);
- lua_setglobal(L, "_VERSION"); /* set global _VERSION */
- + lua_pushliteral(L, LUA_LNUM);
- + lua_setglobal(L, "_LNUM"); /* "[complex] double|float|ldouble int32|int64" */
- /* `ipairs' and `pairs' need auxiliary functions as upvalues */
- auxopen(L, "ipairs", luaB_ipairs, ipairsaux);
- auxopen(L, "pairs", luaB_pairs, luaB_next);
- --- a/src/lcode.c
- +++ b/src/lcode.c
- @@ -22,13 +22,18 @@
- #include "lopcodes.h"
- #include "lparser.h"
- #include "ltable.h"
- +#include "lnum.h"
-
-
- #define hasjumps(e) ((e)->t != (e)->f)
-
- -
- static int isnumeral(expdesc *e) {
- - return (e->k == VKNUM && e->t == NO_JUMP && e->f == NO_JUMP);
- + int ek=
- +#ifdef LNUM_COMPLEX
- + (e->k == VKNUM2) ||
- +#endif
- + (e->k == VKINT) || (e->k == VKNUM);
- + return (ek && e->t == NO_JUMP && e->f == NO_JUMP);
- }
-
-
- @@ -231,12 +236,16 @@ static int addk (FuncState *fs, TValue *
- TValue *idx = luaH_set(L, fs->h, k);
- Proto *f = fs->f;
- int oldsize = f->sizek;
- - if (ttisnumber(idx)) {
- - lua_assert(luaO_rawequalObj(&fs->f->k[cast_int(nvalue(idx))], v));
- - return cast_int(nvalue(idx));
- + if (ttype(idx)==LUA_TNUMBER) {
- + luai_normalize(idx);
- + lua_assert( ttype(idx)==LUA_TINT ); /* had no fraction */
- + }
- + if (ttisint(idx)) {
- + lua_assert(luaO_rawequalObj(&fs->f->k[ivalue(idx)], v));
- + return cast_int(ivalue(idx));
- }
- else { /* constant not found; create a new entry */
- - setnvalue(idx, cast_num(fs->nk));
- + setivalue(idx, fs->nk);
- luaM_growvector(L, f->k, fs->nk, f->sizek, TValue,
- MAXARG_Bx, "constant table overflow");
- while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]);
- @@ -261,6 +270,21 @@ int luaK_numberK (FuncState *fs, lua_Num
- }
-
-
- +int luaK_integerK (FuncState *fs, lua_Integer r) {
- + TValue o;
- + setivalue(&o, r);
- + return addk(fs, &o, &o);
- +}
- +
- +
- +#ifdef LNUM_COMPLEX
- +static int luaK_imagK (FuncState *fs, lua_Number r) {
- + TValue o;
- + setnvalue_complex(&o, r*I);
- + return addk(fs, &o, &o);
- +}
- +#endif
- +
- static int boolK (FuncState *fs, int b) {
- TValue o;
- setbvalue(&o, b);
- @@ -359,6 +383,16 @@ static void discharge2reg (FuncState *fs
- luaK_codeABx(fs, OP_LOADK, reg, luaK_numberK(fs, e->u.nval));
- break;
- }
- + case VKINT: {
- + luaK_codeABx(fs, OP_LOADK, reg, luaK_integerK(fs, e->u.ival));
- + break;
- + }
- +#ifdef LNUM_COMPLEX
- + case VKNUM2: {
- + luaK_codeABx(fs, OP_LOADK, reg, luaK_imagK(fs, e->u.nval));
- + break;
- + }
- +#endif
- case VRELOCABLE: {
- Instruction *pc = &getcode(fs, e);
- SETARG_A(*pc, reg);
- @@ -444,6 +478,10 @@ void luaK_exp2val (FuncState *fs, expdes
- int luaK_exp2RK (FuncState *fs, expdesc *e) {
- luaK_exp2val(fs, e);
- switch (e->k) {
- +#ifdef LNUM_COMPLEX
- + case VKNUM2:
- +#endif
- + case VKINT:
- case VKNUM:
- case VTRUE:
- case VFALSE:
- @@ -451,6 +489,10 @@ int luaK_exp2RK (FuncState *fs, expdesc
- if (fs->nk <= MAXINDEXRK) { /* constant fit in RK operand? */
- e->u.s.info = (e->k == VNIL) ? nilK(fs) :
- (e->k == VKNUM) ? luaK_numberK(fs, e->u.nval) :
- + (e->k == VKINT) ? luaK_integerK(fs, e->u.ival) :
- +#ifdef LNUM_COMPLEX
- + (e->k == VKNUM2) ? luaK_imagK(fs, e->u.nval) :
- +#endif
- boolK(fs, (e->k == VTRUE));
- e->k = VK;
- return RKASK(e->u.s.info);
- @@ -540,7 +582,10 @@ void luaK_goiftrue (FuncState *fs, expde
- int pc; /* pc of last jump */
- luaK_dischargevars(fs, e);
- switch (e->k) {
- - case VK: case VKNUM: case VTRUE: {
- +#ifdef LNUM_COMPLEX
- + case VKNUM2:
- +#endif
- + case VKINT: case VK: case VKNUM: case VTRUE: {
- pc = NO_JUMP; /* always true; do nothing */
- break;
- }
- @@ -590,7 +635,10 @@ static void codenot (FuncState *fs, expd
- e->k = VTRUE;
- break;
- }
- - case VK: case VKNUM: case VTRUE: {
- +#ifdef LNUM_COMPLEX
- + case VKNUM2:
- +#endif
- + case VKINT: case VK: case VKNUM: case VTRUE: {
- e->k = VFALSE;
- break;
- }
- @@ -626,25 +674,70 @@ void luaK_indexed (FuncState *fs, expdes
-
- static int constfolding (OpCode op, expdesc *e1, expdesc *e2) {
- lua_Number v1, v2, r;
- + int vkres= VKNUM;
- if (!isnumeral(e1) || !isnumeral(e2)) return 0;
- - v1 = e1->u.nval;
- - v2 = e2->u.nval;
- +
- + /* real and imaginary parts don't mix. */
- +#ifdef LNUM_COMPLEX
- + if (e1->k == VKNUM2) {
- + if ((op != OP_UNM) && (e2->k != VKNUM2)) return 0;
- + vkres= VKNUM2; }
- + else if (e2->k == VKNUM2) { return 0; }
- +#endif
- + if ((e1->k == VKINT) && (e2->k == VKINT)) {
- + lua_Integer i1= e1->u.ival, i2= e2->u.ival;
- + lua_Integer rr;
- + int done= 0;
- + /* Integer/integer calculations (may end up producing floating point) */
- + switch (op) {
- + case OP_ADD: done= try_addint( &rr, i1, i2 ); break;
- + case OP_SUB: done= try_subint( &rr, i1, i2 ); break;
- + case OP_MUL: done= try_mulint( &rr, i1, i2 ); break;
- + case OP_DIV: done= try_divint( &rr, i1, i2 ); break;
- + case OP_MOD: done= try_modint( &rr, i1, i2 ); break;
- + case OP_POW: done= try_powint( &rr, i1, i2 ); break;
- + case OP_UNM: done= try_unmint( &rr, i1 ); break;
- + default: done= 0; break;
- + }
- + if (done) {
- + e1->u.ival = rr; /* remained within integer range */
- + return 1;
- + }
- + }
- + v1 = (e1->k == VKINT) ? ((lua_Number)e1->u.ival) : e1->u.nval;
- + v2 = (e2->k == VKINT) ? ((lua_Number)e2->u.ival) : e2->u.nval;
- +
- switch (op) {
- case OP_ADD: r = luai_numadd(v1, v2); break;
- case OP_SUB: r = luai_numsub(v1, v2); break;
- - case OP_MUL: r = luai_nummul(v1, v2); break;
- + case OP_MUL:
- +#ifdef LNUM_COMPLEX
- + if (vkres==VKNUM2) return 0; /* leave to runtime (could do here, but not worth it?) */
- +#endif
- + r = luai_nummul(v1, v2); break;
- case OP_DIV:
- if (v2 == 0) return 0; /* do not attempt to divide by 0 */
- - r = luai_numdiv(v1, v2); break;
- +#ifdef LNUM_COMPLEX
- + if (vkres==VKNUM2) return 0; /* leave to runtime */
- +#endif
- + r = luai_numdiv(v1, v2); break;
- case OP_MOD:
- if (v2 == 0) return 0; /* do not attempt to divide by 0 */
- +#ifdef LNUM_COMPLEX
- + if (vkres==VKNUM2) return 0; /* leave to runtime */
- +#endif
- r = luai_nummod(v1, v2); break;
- - case OP_POW: r = luai_numpow(v1, v2); break;
- + case OP_POW:
- +#ifdef LNUM_COMPLEX
- + if (vkres==VKNUM2) return 0; /* leave to runtime */
- +#endif
- + r = luai_numpow(v1, v2); break;
- case OP_UNM: r = luai_numunm(v1); break;
- case OP_LEN: return 0; /* no constant folding for 'len' */
- default: lua_assert(0); r = 0; break;
- }
- if (luai_numisnan(r)) return 0; /* do not attempt to produce NaN */
- + e1->k = cast(expkind,vkres);
- e1->u.nval = r;
- return 1;
- }
- @@ -688,7 +781,8 @@ static void codecomp (FuncState *fs, OpC
-
- void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e) {
- expdesc e2;
- - e2.t = e2.f = NO_JUMP; e2.k = VKNUM; e2.u.nval = 0;
- + e2.t = e2.f = NO_JUMP; e2.k = VKINT; e2.u.ival = 0;
- +
- switch (op) {
- case OPR_MINUS: {
- if (!isnumeral(e))
- --- a/src/lcode.h
- +++ b/src/lcode.h
- @@ -71,6 +71,6 @@ LUAI_FUNC void luaK_prefix (FuncState *f
- LUAI_FUNC void luaK_infix (FuncState *fs, BinOpr op, expdesc *v);
- LUAI_FUNC void luaK_posfix (FuncState *fs, BinOpr op, expdesc *v1, expdesc *v2);
- LUAI_FUNC void luaK_setlist (FuncState *fs, int base, int nelems, int tostore);
- -
- +LUAI_FUNC int luaK_integerK (FuncState *fs, lua_Integer r);
-
- #endif
- --- a/src/ldebug.c
- +++ b/src/ldebug.c
- @@ -183,7 +183,7 @@ static void collectvalidlines (lua_State
- int *lineinfo = f->l.p->lineinfo;
- int i;
- for (i=0; i<f->l.p->sizelineinfo; i++)
- - setbvalue(luaH_setnum(L, t, lineinfo[i]), 1);
- + setbvalue(luaH_setint(L, t, lineinfo[i]), 1);
- sethvalue(L, L->top, t);
- }
- incr_top(L);
- @@ -566,7 +566,7 @@ static int isinstack (CallInfo *ci, cons
-
- void luaG_typeerror (lua_State *L, const TValue *o, const char *op) {
- const char *name = NULL;
- - const char *t = luaT_typenames[ttype(o)];
- + const char *t = luaT_typenames[ttype_ext(o)];
- const char *kind = (isinstack(L->ci, o)) ?
- getobjname(L, L->ci, cast_int(o - L->base), &name) :
- NULL;
- @@ -594,8 +594,8 @@ void luaG_aritherror (lua_State *L, cons
-
-
- int luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) {
- - const char *t1 = luaT_typenames[ttype(p1)];
- - const char *t2 = luaT_typenames[ttype(p2)];
- + const char *t1 = luaT_typenames[ttype_ext(p1)];
- + const char *t2 = luaT_typenames[ttype_ext(p2)];
- if (t1[2] == t2[2])
- luaG_runerror(L, "attempt to compare two %s values", t1);
- else
- --- a/src/ldo.c
- +++ b/src/ldo.c
- @@ -220,9 +220,9 @@ static StkId adjust_varargs (lua_State *
- luaD_checkstack(L, p->maxstacksize);
- htab = luaH_new(L, nvar, 1); /* create `arg' table */
- for (i=0; i<nvar; i++) /* put extra arguments into `arg' table */
- - setobj2n(L, luaH_setnum(L, htab, i+1), L->top - nvar + i);
- + setobj2n(L, luaH_setint(L, htab, i+1), L->top - nvar + i);
- /* store counter in field `n' */
- - setnvalue(luaH_setstr(L, htab, luaS_newliteral(L, "n")), cast_num(nvar));
- + setivalue(luaH_setstr(L, htab, luaS_newliteral(L, "n")), nvar);
- }
- #endif
- /* move fixed parameters to final position */
- --- a/src/ldump.c
- +++ b/src/ldump.c
- @@ -52,6 +52,11 @@ static void DumpNumber(lua_Number x, Dum
- DumpVar(x,D);
- }
-
- +static void DumpInteger(lua_Integer x, DumpState* D)
- +{
- + DumpVar(x,D);
- +}
- +
- static void DumpVector(const void* b, int n, size_t size, DumpState* D)
- {
- DumpInt(n,D);
- @@ -93,8 +98,11 @@ static void DumpConstants(const Proto* f
- DumpChar(bvalue(o),D);
- break;
- case LUA_TNUMBER:
- - DumpNumber(nvalue(o),D);
- + DumpNumber(nvalue_fast(o),D);
- break;
- + case LUA_TINT:
- + DumpInteger(ivalue(o),D);
- + break;
- case LUA_TSTRING:
- DumpString(rawtsvalue(o),D);
- break;
- --- a/src/liolib.c
- +++ b/src/liolib.c
- @@ -9,6 +9,7 @@
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- +#include <ctype.h>
-
- #define liolib_c
- #define LUA_LIB
- @@ -18,7 +19,8 @@
- #include "lauxlib.h"
- #include "lualib.h"
-
- -
- +#include "lnum.h"
- +#include "llex.h"
-
- #define IO_INPUT 1
- #define IO_OUTPUT 2
- @@ -269,6 +271,13 @@ static int io_lines (lua_State *L) {
- ** =======================================================
- */
-
- +/*
- +* Many problems if we intend the same 'n' format specifier (see 'file:read()')
- +* to work for both FP and integer numbers, without losing their accuracy. So
- +* we don't. 'n' reads numbers as floating points, 'i' as integers. Old code
- +* remains valid, but won't provide full integer accuracy (this only matters
- +* with float FP and/or 64-bit integers).
- +*/
-
- static int read_number (lua_State *L, FILE *f) {
- lua_Number d;
- @@ -282,6 +291,43 @@ static int read_number (lua_State *L, FI
- }
- }
-
- +static int read_integer (lua_State *L, FILE *f) {
- + lua_Integer i;
- + if (fscanf(f, LUA_INTEGER_SCAN, &i) == 1) {
- + lua_pushinteger(L, i);
- + return 1;
- + }
- + else return 0; /* read fails */
- +}
- +
- +#ifdef LNUM_COMPLEX
- +static int read_complex (lua_State *L, FILE *f) {
- + /* NNN / NNNi / NNN+MMMi / NNN-MMMi */
- + lua_Number a,b;
- + if (fscanf(f, LUA_NUMBER_SCAN, &a) == 1) {
- + int c=fgetc(f);
- + switch(c) {
- + case 'i':
- + lua_pushcomplex(L, a*I);
- + return 1;
- + case '+':
- + case '-':
- + /* "i" is consumed if at the end; just 'NNN+MMM' will most likely
- + * behave as if "i" was there? (TBD: test)
- + */
- + if (fscanf(f, LUA_NUMBER_SCAN "i", &b) == 1) {
- + lua_pushcomplex(L, a+ (c=='+' ? b:-b)*I);
- + return 1;
- + }
- + }
- + ungetc( c,f );
- + lua_pushnumber(L,a); /*real part only*/
- + return 1;
- + }
- + return 0; /* read fails */
- +}
- +#endif
- +
-
- static int test_eof (lua_State *L, FILE *f) {
- int c = getc(f);
- @@ -355,6 +401,14 @@ static int g_read (lua_State *L, FILE *f
- case 'n': /* number */
- success = read_number(L, f);
- break;
- + case 'i': /* integer (full accuracy) */
- + success = read_integer(L, f);
- + break;
- +#ifdef LNUM_COMPLEX
- + case 'c': /* complex */
- + success = read_complex(L, f);
- + break;
- +#endif
- case 'l': /* line */
- success = read_line(L, f);
- break;
- @@ -415,9 +469,10 @@ static int g_write (lua_State *L, FILE *
- int status = 1;
- for (; nargs--; arg++) {
- if (lua_type(L, arg) == LUA_TNUMBER) {
- - /* optimization: could be done exactly as for strings */
- - status = status &&
- - fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0;
- + if (lua_isinteger(L,arg))
- + status = status && fprintf(f, LUA_INTEGER_FMT, lua_tointeger(L, arg)) > 0;
- + else
- + status = status && fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0;
- }
- else {
- size_t l;
- @@ -460,7 +515,7 @@ static int f_setvbuf (lua_State *L) {
- static const char *const modenames[] = {"no", "full", "line", NULL};
- FILE *f = tofile(L);
- int op = luaL_checkoption(L, 2, NULL, modenames);
- - lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE);
- + size_t sz = luaL_optint32(L, 3, LUAL_BUFFERSIZE);
- int res = setvbuf(f, NULL, mode[op], sz);
- return pushresult(L, res == 0, NULL);
- }
- --- a/src/llex.c
- +++ b/src/llex.c
- @@ -22,6 +22,7 @@
- #include "lstring.h"
- #include "ltable.h"
- #include "lzio.h"
- +#include "lnum.h"
-
-
-
- @@ -34,13 +35,17 @@
-
-
- /* ORDER RESERVED */
- -const char *const luaX_tokens [] = {
- +static const char *const luaX_tokens [] = {
- "and", "break", "do", "else", "elseif",
- "end", "false", "for", "function", "if",
- "in", "local", "nil", "not", "or", "repeat",
- "return", "then", "true", "until", "while",
- "..", "...", "==", ">=", "<=", "~=",
- "<number>", "<name>", "<string>", "<eof>",
- + "<integer>",
- +#ifdef LNUM_COMPLEX
- + "<number2>",
- +#endif
- NULL
- };
-
- @@ -90,7 +95,11 @@ static const char *txtToken (LexState *l
- switch (token) {
- case TK_NAME:
- case TK_STRING:
- + case TK_INT:
- case TK_NUMBER:
- +#ifdef LNUM_COMPLEX
- + case TK_NUMBER2:
- +#endif
- save(ls, '\0');
- return luaZ_buffer(ls->buff);
- default:
- @@ -175,23 +184,27 @@ static void buffreplace (LexState *ls, c
- if (p[n] == from) p[n] = to;
- }
-
- -
- -static void trydecpoint (LexState *ls, SemInfo *seminfo) {
- +/* TK_NUMBER (/ TK_NUMBER2) */
- +static int trydecpoint (LexState *ls, SemInfo *seminfo) {
- /* format error: try to update decimal point separator */
- struct lconv *cv = localeconv();
- char old = ls->decpoint;
- + int ret;
- ls->decpoint = (cv ? cv->decimal_point[0] : '.');
- buffreplace(ls, old, ls->decpoint); /* try updated decimal separator */
- - if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r)) {
- + ret= luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r, NULL);
- + if (!ret) {
- /* format error with correct decimal point: no more options */
- buffreplace(ls, ls->decpoint, '.'); /* undo change (for error message) */
- luaX_lexerror(ls, "malformed number", TK_NUMBER);
- }
- + return ret;
- }
-
-
- -/* LUA_NUMBER */
- -static void read_numeral (LexState *ls, SemInfo *seminfo) {
- +/* TK_NUMBER / TK_INT (/TK_NUMBER2) */
- +static int read_numeral (LexState *ls, SemInfo *seminfo) {
- + int ret;
- lua_assert(isdigit(ls->current));
- do {
- save_and_next(ls);
- @@ -202,8 +215,9 @@ static void read_numeral (LexState *ls,
- save_and_next(ls);
- save(ls, '\0');
- buffreplace(ls, '.', ls->decpoint); /* follow locale for decimal point */
- - if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r)) /* format error? */
- - trydecpoint(ls, seminfo); /* try to update decimal point separator */
- + ret= luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r, &seminfo->i );
- + if (!ret) return trydecpoint(ls, seminfo); /* try to update decimal point separator */
- + return ret;
- }
-
-
- @@ -331,6 +345,7 @@ static void read_string (LexState *ls, i
- }
-
-
- +/* char / TK_* */
- static int llex (LexState *ls, SemInfo *seminfo) {
- luaZ_resetbuffer(ls->buff);
- for (;;) {
- @@ -402,8 +417,7 @@ static int llex (LexState *ls, SemInfo *
- }
- else if (!isdigit(ls->current)) return '.';
- else {
- - read_numeral(ls, seminfo);
- - return TK_NUMBER;
- + return read_numeral(ls, seminfo);
- }
- }
- case EOZ: {
- @@ -416,8 +430,7 @@ static int llex (LexState *ls, SemInfo *
- continue;
- }
- else if (isdigit(ls->current)) {
- - read_numeral(ls, seminfo);
- - return TK_NUMBER;
- + return read_numeral(ls, seminfo);
- }
- else if (isalpha(ls->current) || ls->current == '_') {
- /* identifier or reserved word */
- --- a/src/llex.h
- +++ b/src/llex.h
- @@ -29,19 +29,22 @@ enum RESERVED {
- TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE,
- /* other terminal symbols */
- TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, TK_NUMBER,
- - TK_NAME, TK_STRING, TK_EOS
- + TK_NAME, TK_STRING, TK_EOS, TK_INT
- +#ifdef LNUM_COMPLEX
- + , TK_NUMBER2 /* imaginary constants: Ni */
- +#endif
- };
-
- /* number of reserved words */
- #define NUM_RESERVED (cast(int, TK_WHILE-FIRST_RESERVED+1))
-
-
- -/* array with token `names' */
- -LUAI_DATA const char *const luaX_tokens [];
- -
- -
- +/* SemInfo is a local data structure of 'llex.c', used for carrying a string
- + * or a number. A separate token (TK_*) will tell, how to interpret the data.
- + */
- typedef union {
- lua_Number r;
- + lua_Integer i;
- TString *ts;
- } SemInfo; /* semantics information */
-
- --- a/src/llimits.h
- +++ b/src/llimits.h
- @@ -49,6 +49,7 @@ typedef LUAI_USER_ALIGNMENT_T L_Umaxalig
-
- /* result of a `usual argument conversion' over lua_Number */
- typedef LUAI_UACNUMBER l_uacNumber;
- +typedef LUAI_UACINTEGER l_uacInteger;
-
-
- /* internal assertions for in-house debugging */
- @@ -80,7 +81,6 @@ typedef LUAI_UACNUMBER l_uacNumber;
- #define cast_int(i) cast(int, (i))
-
-
- -
- /*
- ** type for virtual-machine instructions
- ** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h)
- --- a/src/lmathlib.c
- +++ b/src/lmathlib.c
- @@ -4,7 +4,6 @@
- ** See Copyright Notice in lua.h
- */
-
- -
- #include <stdlib.h>
- #include <math.h>
-
- @@ -16,113 +15,210 @@
- #include "lauxlib.h"
- #include "lualib.h"
-
- +/* 'luai_vectpow()' as a replacement for 'cpow()'. Defined in the header; we
- + * don't intrude the code libs internal functions.
- + */
- +#ifdef LNUM_COMPLEX
- +# include "lnum.h"
- +#endif
-
- #undef PI
- -#define PI (3.14159265358979323846)
- -#define RADIANS_PER_DEGREE (PI/180.0)
- -
- +#ifdef LNUM_FLOAT
- +# define PI (3.14159265358979323846F)
- +#elif defined(M_PI)
- +# define PI M_PI
- +#else
- +# define PI (3.14159265358979323846264338327950288)
- +#endif
- +#define RADIANS_PER_DEGREE (PI/180)
-
- +#undef HUGE
- +#ifdef LNUM_FLOAT
- +# define HUGE HUGE_VALF
- +#elif defined(LNUM_LDOUBLE)
- +# define HUGE HUGE_VALL
- +#else
- +# define HUGE HUGE_VAL
- +#endif
-
- static int math_abs (lua_State *L) {
- - lua_pushnumber(L, fabs(luaL_checknumber(L, 1)));
- +#ifdef LNUM_COMPLEX
- + lua_pushnumber(L, _LF(cabs) (luaL_checkcomplex(L,1)));
- +#else
- + lua_pushnumber(L, _LF(fabs) (luaL_checknumber(L, 1)));
- +#endif
- return 1;
- }
-
- static int math_sin (lua_State *L) {
- - lua_pushnumber(L, sin(luaL_checknumber(L, 1)));
- +#ifdef LNUM_COMPLEX
- + lua_pushcomplex(L, _LF(csin) (luaL_checkcomplex(L,1)));
- +#else
- + lua_pushnumber(L, _LF(sin) (luaL_checknumber(L, 1)));
- +#endif
- return 1;
- }
-
- static int math_sinh (lua_State *L) {
- - lua_pushnumber(L, sinh(luaL_checknumber(L, 1)));
- +#ifdef LNUM_COMPLEX
- + lua_pushcomplex(L, _LF(csinh) (luaL_checkcomplex(L,1)));
- +#else
- + lua_pushnumber(L, _LF(sinh) (luaL_checknumber(L, 1)));
- +#endif
- return 1;
- }
-
- static int math_cos (lua_State *L) {
- - lua_pushnumber(L, cos(luaL_checknumber(L, 1)));
- +#ifdef LNUM_COMPLEX
- + lua_pushcomplex(L, _LF(ccos) (luaL_checkcomplex(L,1)));
- +#else
- + lua_pushnumber(L, _LF(cos) (luaL_checknumber(L, 1)));
- +#endif
- return 1;
- }
-
- static int math_cosh (lua_State *L) {
- - lua_pushnumber(L, cosh(luaL_checknumber(L, 1)));
- +#ifdef LNUM_COMPLEX
- + lua_pushcomplex(L, _LF(ccosh) (luaL_checkcomplex(L,1)));
- +#else
- + lua_pushnumber(L, _LF(cosh) (luaL_checknumber(L, 1)));
- +#endif
- return 1;
- }
-
- static int math_tan (lua_State *L) {
- - lua_pushnumber(L, tan(luaL_checknumber(L, 1)));
- +#ifdef LNUM_COMPLEX
- + lua_pushcomplex(L, _LF(ctan) (luaL_checkcomplex(L,1)));
- +#else
- + lua_pushnumber(L, _LF(tan) (luaL_checknumber(L, 1)));
- +#endif
- return 1;
- }
-
- static int math_tanh (lua_State *L) {
- - lua_pushnumber(L, tanh(luaL_checknumber(L, 1)));
- +#ifdef LNUM_COMPLEX
- + lua_pushcomplex(L, _LF(ctanh) (luaL_checkcomplex(L,1)));
- +#else
- + lua_pushnumber(L, _LF(tanh) (luaL_checknumber(L, 1)));
- +#endif
- return 1;
- }
-
- static int math_asin (lua_State *L) {
- - lua_pushnumber(L, asin(luaL_checknumber(L, 1)));
- +#ifdef LNUM_COMPLEX
- + lua_pushcomplex(L, _LF(casin) (luaL_checkcomplex(L,1)));
- +#else
- + lua_pushnumber(L, _LF(asin) (luaL_checknumber(L, 1)));
- +#endif
- return 1;
- }
-
- static int math_acos (lua_State *L) {
- - lua_pushnumber(L, acos(luaL_checknumber(L, 1)));
- +#ifdef LNUM_COMPLEX
- + lua_pushcomplex(L, _LF(cacos) (luaL_checkcomplex(L,1)));
- +#else
- + lua_pushnumber(L, _LF(acos) (luaL_checknumber(L, 1)));
- +#endif
- return 1;
- }
-
- static int math_atan (lua_State *L) {
- - lua_pushnumber(L, atan(luaL_checknumber(L, 1)));
- +#ifdef LNUM_COMPLEX
- + lua_pushcomplex(L, _LF(catan) (luaL_checkcomplex(L,1)));
- +#else
- + lua_pushnumber(L, _LF(atan) (luaL_checknumber(L, 1)));
- +#endif
- return 1;
- }
-
- static int math_atan2 (lua_State *L) {
- - lua_pushnumber(L, atan2(luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
- + /* scalars only */
- + lua_pushnumber(L, _LF(atan2) (luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
- return 1;
- }
-
- static int math_ceil (lua_State *L) {
- - lua_pushnumber(L, ceil(luaL_checknumber(L, 1)));
- +#ifdef LNUM_COMPLEX
- + lua_Complex v= luaL_checkcomplex(L, 1);
- + lua_pushcomplex(L, _LF(ceil) (_LF(creal)(v)) + _LF(ceil) (_LF(cimag)(v))*I);
- +#else
- + lua_pushnumber(L, _LF(ceil) (luaL_checknumber(L, 1)));
- +#endif
- return 1;
- }
-
- static int math_floor (lua_State *L) {
- - lua_pushnumber(L, floor(luaL_checknumber(L, 1)));
- +#ifdef LNUM_COMPLEX
- + lua_Complex v= luaL_checkcomplex(L, 1);
- + lua_pushcomplex(L, _LF(floor) (_LF(creal)(v)) + _LF(floor) (_LF(cimag)(v))*I);
- +#else
- + lua_pushnumber(L, _LF(floor) (luaL_checknumber(L, 1)));
- +#endif
- return 1;
- }
-
- -static int math_fmod (lua_State *L) {
- - lua_pushnumber(L, fmod(luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
- +static int math_fmod (lua_State *L) {
- + /* scalars only */
- + lua_pushnumber(L, _LF(fmod) (luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
- return 1;
- }
-
- static int math_modf (lua_State *L) {
- - double ip;
- - double fp = modf(luaL_checknumber(L, 1), &ip);
- + /* scalars only */
- + lua_Number ip;
- + lua_Number fp = _LF(modf) (luaL_checknumber(L, 1), &ip);
- lua_pushnumber(L, ip);
- lua_pushnumber(L, fp);
- return 2;
- }
-
- static int math_sqrt (lua_State *L) {
- - lua_pushnumber(L, sqrt(luaL_checknumber(L, 1)));
- +#ifdef LNUM_COMPLEX
- + lua_pushcomplex(L, _LF(csqrt) (luaL_checkcomplex(L,1)));
- +#else
- + lua_pushnumber(L, _LF(sqrt) (luaL_checknumber(L, 1)));
- +#endif
- return 1;
- }
-
- static int math_pow (lua_State *L) {
- - lua_pushnumber(L, pow(luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
- +#ifdef LNUM_COMPLEX
- + /* C99 'cpow' gives somewhat inaccurate results (i.e. (-1)^2 = -1+1.2246467991474e-16i).
- + * 'luai_vectpow' smoothens such, reusing it is the reason we need to #include "lnum.h".
- + */
- + lua_pushcomplex(L, luai_vectpow(luaL_checkcomplex(L,1), luaL_checkcomplex(L,2)));
- +#else
- + lua_pushnumber(L, _LF(pow) (luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
- +#endif
- return 1;
- }
-
- static int math_log (lua_State *L) {
- - lua_pushnumber(L, log(luaL_checknumber(L, 1)));
- +#ifdef LNUM_COMPLEX
- + lua_pushcomplex(L, _LF(clog) (luaL_checkcomplex(L,1)));
- +#else
- + lua_pushnumber(L, _LF(log) (luaL_checknumber(L, 1)));
- +#endif
- return 1;
- }
-
- static int math_log10 (lua_State *L) {
- - lua_pushnumber(L, log10(luaL_checknumber(L, 1)));
- +#ifdef LNUM_COMPLEX
- + /* Not in standard <complex.h> , but easy to calculate: log_a(x) = log_b(x) / log_b(a)
- + */
- + lua_pushcomplex(L, _LF(clog) (luaL_checkcomplex(L,1)) / _LF(log) (10));
- +#else
- + lua_pushnumber(L, _LF(log10) (luaL_checknumber(L, 1)));
- +#endif
- return 1;
- }
-
- static int math_exp (lua_State *L) {
- - lua_pushnumber(L, exp(luaL_checknumber(L, 1)));
- +#ifdef LNUM_COMPLEX
- + lua_pushcomplex(L, _LF(cexp) (luaL_checkcomplex(L,1)));
- +#else
- + lua_pushnumber(L, _LF(exp) (luaL_checknumber(L, 1)));
- +#endif
- return 1;
- }
-
- @@ -138,19 +234,20 @@ static int math_rad (lua_State *L) {
-
- static int math_frexp (lua_State *L) {
- int e;
- - lua_pushnumber(L, frexp(luaL_checknumber(L, 1), &e));
- + lua_pushnumber(L, _LF(frexp) (luaL_checknumber(L, 1), &e));
- lua_pushinteger(L, e);
- return 2;
- }
-
- static int math_ldexp (lua_State *L) {
- - lua_pushnumber(L, ldexp(luaL_checknumber(L, 1), luaL_checkint(L, 2)));
- + lua_pushnumber(L, _LF(ldexp) (luaL_checknumber(L, 1), luaL_checkint(L, 2)));
- return 1;
- }
-
-
-
- static int math_min (lua_State *L) {
- + /* scalars only */
- int n = lua_gettop(L); /* number of arguments */
- lua_Number dmin = luaL_checknumber(L, 1);
- int i;
- @@ -165,6 +262,7 @@ static int math_min (lua_State *L) {
-
-
- static int math_max (lua_State *L) {
- + /* scalars only */
- int n = lua_gettop(L); /* number of arguments */
- lua_Number dmax = luaL_checknumber(L, 1);
- int i;
- @@ -182,25 +280,20 @@ static int math_random (lua_State *L) {
- /* the `%' avoids the (rare) case of r==1, and is needed also because on
- some systems (SunOS!) `rand()' may return a value larger than RAND_MAX */
- lua_Number r = (lua_Number)(rand()%RAND_MAX) / (lua_Number)RAND_MAX;
- - switch (lua_gettop(L)) { /* check number of arguments */
- - case 0: { /* no arguments */
- - lua_pushnumber(L, r); /* Number between 0 and 1 */
- - break;
- - }
- - case 1: { /* only upper limit */
- - int u = luaL_checkint(L, 1);
- - luaL_argcheck(L, 1<=u, 1, "interval is empty");
- - lua_pushnumber(L, floor(r*u)+1); /* int between 1 and `u' */
- - break;
- - }
- - case 2: { /* lower and upper limits */
- - int l = luaL_checkint(L, 1);
- - int u = luaL_checkint(L, 2);
- - luaL_argcheck(L, l<=u, 2, "interval is empty");
- - lua_pushnumber(L, floor(r*(u-l+1))+l); /* int between `l' and `u' */
- - break;
- - }
- - default: return luaL_error(L, "wrong number of arguments");
- + int n= lua_gettop(L); /* number of arguments */
- + if (n==0) { /* no arguments: range [0,1) */
- + lua_pushnumber(L, r);
- + } else if (n<=2) { /* int range [1,u] or [l,u] */
- + int l= n==1 ? 1 : luaL_checkint(L, 1);
- + int u = luaL_checkint(L, n);
- + int tmp;
- + lua_Number d;
- + luaL_argcheck(L, l<=u, n, "interval is empty");
- + d= _LF(floor)(r*(u-l+1));
- + lua_number2int(tmp,d);
- + lua_pushinteger(L, l+tmp);
- + } else {
- + return luaL_error(L, "wrong number of arguments");
- }
- return 1;
- }
- @@ -211,6 +304,66 @@ static int math_randomseed (lua_State *L
- return 0;
- }
-
- +/*
- +* Lua 5.1 does not have acosh, asinh, atanh for scalars (not ANSI C)
- +*/
- +#if __STDC_VERSION__ >= 199901L
- +static int math_acosh (lua_State *L) {
- +# ifdef LNUM_COMPLEX
- + lua_pushcomplex(L, _LF(cacosh) (luaL_checkcomplex(L,1)));
- +# else
- + lua_pushnumber(L, _LF(acosh) (luaL_checknumber(L,1)));
- +# endif
- + return 1;
- +}
- +static int math_asinh (lua_State *L) {
- +# ifdef LNUM_COMPLEX
- + lua_pushcomplex(L, _LF(casinh) (luaL_checkcomplex(L,1)));
- +# else
- + lua_pushnumber(L, _LF(asinh) (luaL_checknumber(L,1)));
- +# endif
- + return 1;
- +}
- +static int math_atanh (lua_State *L) {
- +# ifdef LNUM_COMPLEX
- + lua_pushcomplex(L, _LF(catanh) (luaL_checkcomplex(L,1)));
- +# else
- + lua_pushnumber(L, _LF(atanh) (luaL_checknumber(L,1)));
- +# endif
- + return 1;
- +}
- +#endif
- +
- +/*
- + * C99 complex functions, not covered above.
- +*/
- +#ifdef LNUM_COMPLEX
- +static int math_arg (lua_State *L) {
- + lua_pushnumber(L, _LF(carg) (luaL_checkcomplex(L,1)));
- + return 1;
- +}
- +
- +static int math_imag (lua_State *L) {
- + lua_pushnumber(L, _LF(cimag) (luaL_checkcomplex(L,1)));
- + return 1;
- +}
- +
- +static int math_real (lua_State *L) {
- + lua_pushnumber(L, _LF(creal) (luaL_checkcomplex(L,1)));
- + return 1;
- +}
- +
- +static int math_conj (lua_State *L) {
- + lua_pushcomplex(L, _LF(conj) (luaL_checkcomplex(L,1)));
- + return 1;
- +}
- +
- +static int math_proj (lua_State *L) {
- + lua_pushcomplex(L, _LF(cproj) (luaL_checkcomplex(L,1)));
- + return 1;
- +}
- +#endif
- +
-
- static const luaL_Reg mathlib[] = {
- {"abs", math_abs},
- @@ -241,6 +394,18 @@ static const luaL_Reg mathlib[] = {
- {"sqrt", math_sqrt},
- {"tanh", math_tanh},
- {"tan", math_tan},
- +#if __STDC_VERSION__ >= 199901L
- + {"acosh", math_acosh},
- + {"asinh", math_asinh},
- + {"atanh", math_atanh},
- +#endif
- +#ifdef LNUM_COMPLEX
- + {"arg", math_arg},
- + {"imag", math_imag},
- + {"real", math_real},
- + {"conj", math_conj},
- + {"proj", math_proj},
- +#endif
- {NULL, NULL}
- };
-
- @@ -252,8 +417,10 @@ LUALIB_API int luaopen_math (lua_State *
- luaL_register(L, LUA_MATHLIBNAME, mathlib);
- lua_pushnumber(L, PI);
- lua_setfield(L, -2, "pi");
- - lua_pushnumber(L, HUGE_VAL);
- + lua_pushnumber(L, HUGE);
- lua_setfield(L, -2, "huge");
- + lua_pushinteger(L, LUA_INTEGER_MAX );
- + lua_setfield(L, -2, "hugeint");
- #if defined(LUA_COMPAT_MOD)
- lua_getfield(L, -1, "fmod");
- lua_setfield(L, -2, "mod");
- --- /dev/null
- +++ b/src/lnum.c
- @@ -0,0 +1,312 @@
- +/*
- +** $Id: lnum.c,v ... $
- +** Internal number model
- +** See Copyright Notice in lua.h
- +*/
- +
- +#include <stdlib.h>
- +#include <math.h>
- +#include <ctype.h>
- +#include <string.h>
- +#include <stdio.h>
- +#include <errno.h>
- +
- +#define lnum_c
- +#define LUA_CORE
- +
- +#include "lua.h"
- +#include "llex.h"
- +#include "lnum.h"
- +
- +/*
- +** lua_real2str converts a (non-complex) number to a string.
- +** lua_str2real converts a string to a (non-complex) number.
- +*/
- +#define lua_real2str(s,n) sprintf((s), LUA_NUMBER_FMT, (n))
- +
- +/*
- +* Note: Only 'strtod()' is part of ANSI C; others are C99 and
- +* may need '--std=c99' compiler setting (at least on Ubuntu 7.10).
- +*
- +* Visual C++ 2008 Express does not have 'strtof()', nor 'strtold()'.
- +* References to '_strtold()' exist but don't compile. It seems best
- +* to leave Windows users with DOUBLE only (or compile with MinGW).
- +*
- +* In practise, using '(long double)strtod' is a risky thing, since
- +* it will cause accuracy loss in reading in numbers, and such losses
- +* will pile up in later processing. Get a real 'strtold()' or don't
- +* use that mode at all.
- +*/
- +#ifdef LNUM_DOUBLE
- +# define lua_str2real strtod
- +#elif defined(LNUM_FLOAT)
- +# define lua_str2real strtof
- +#elif defined(LNUM_LDOUBLE)
- +# define lua_str2real strtold
- +#endif
- +
- +#define lua_integer2str(s,v) sprintf((s), LUA_INTEGER_FMT, (v))
- +
- +/* 's' is expected to be LUAI_MAXNUMBER2STR long (enough for any number)
- +*/
- +void luaO_num2buf( char *s, const TValue *o )
- +{
- + lua_Number n;
- + lua_assert( ttisnumber(o) );
- +
- + /* Reason to handle integers differently is not only speed, but accuracy as
- + * well. We want to make any integer tostring() without roundings, at all.
- + */
- + if (ttisint(o)) {
- + lua_integer2str( s, ivalue(o) );
- + return;
- + }
- + n= nvalue_fast(o);
- + lua_real2str(s, n);
- +
- +#ifdef LNUM_COMPLEX
- + lua_Number n2= nvalue_img_fast(o);
- + if (n2!=0) { /* Postfix with +-Ni */
- + int re0= (n == 0);
- + char *s2= re0 ? s : strchr(s,'\0');
- + if ((!re0) && (n2>0)) *s2++= '+';
- + lua_real2str( s2, n2 );
- + strcat(s2,"i");
- + }
- +#endif
- +}
- +
- +/*
- +* If a LUA_TNUMBER has integer value, give it.
- +*/
- +int /*bool*/ tt_integer_valued( const TValue *o, lua_Integer *ref ) {
- + lua_Number d;
- + lua_Integer i;
- +
- + lua_assert( ttype(o)==LUA_TNUMBER );
- + lua_assert( ref );
- +#ifdef LNUM_COMPLEX
- + if (nvalue_img_fast(o)!=0) return 0;
- +#endif
- + d= nvalue_fast(o);
- + lua_number2integer(i, d);
- + if (cast_num(i) == d) {
- + *ref= i; return 1;
- + }
- + return 0;
- +}
- +
- +/*
- + * Lua 5.1.3 (using 'strtod()') allows 0x+hex but not 0+octal. This is good,
- + * and we should NOT use 'autobase' 0 with 'strtoul[l]()' for this reason.
- + *
- + * Lua 5.1.3 allows '0x...' numbers to overflow and lose precision; this is not
- + * good. On Visual C++ 2008, 'strtod()' does not even take them in. Better to
- + * require hex values to fit 'lua_Integer' or give an error that they don't?
- + *
- + * Full hex range (0 .. 0xff..ff) is stored as integers, not to lose any bits.
- + * Numerical value of 0xff..ff will be -1, if used in calculations.
- + *
- + * Returns: TK_INT for a valid integer, '*endptr_ref' updated
- + * TK_NUMBER for seemingly numeric, to be parsed as floating point
- + * 0 for bad characters, not a number (or '0x' out of range)
- + */
- +static int luaO_str2i (const char *s, lua_Integer *res, char **endptr_ref) {
- + char *endptr;
- + /* 'v' gets ULONG_MAX on possible overflow (which is > LUA_INTEGER_MAX);
- + * we don't have to check 'errno' here.
- + */
- + unsigned LUA_INTEGER v= lua_str2ul(s, &endptr, 10);
- + if (endptr == s) return 0; /* nothing numeric */
- + if (v==0 && *endptr=='x') {
- + errno= 0; /* needs to be set, 'strtoul[l]' does not clear it */
- + v= lua_str2ul(endptr+1, &endptr, 16); /* retry as hex, unsigned range */
- + if (errno==ERANGE) { /* clamped to 0xff..ff */
- +#if (defined(LNUM_INT32) && !defined(LNUM_FLOAT)) || defined(LNUM_LDOUBLE)
- + return TK_NUMBER; /* Allow to be read as floating point (has more integer range) */
- +#else
- + return 0; /* Reject the number */
- +#endif
- + }
- + } else if ((v > LUA_INTEGER_MAX) || (*endptr && (!isspace(*endptr)))) {
- + return TK_NUMBER; /* not in signed range, or has '.', 'e' etc. trailing */
- + }
- + *res= (lua_Integer)v;
- + *endptr_ref= endptr;
- + return TK_INT;
- +}
- +
- +/* 0 / TK_NUMBER / TK_INT (/ TK_NUMBER2) */
- +int luaO_str2d (const char *s, lua_Number *res_n, lua_Integer *res_i) {
- + char *endptr;
- + int ret= TK_NUMBER;
- + /* Check integers first, if caller is allowing.
- + * If 'res2'==NULL, they're only looking for floating point.
- + */
- + if (res_i) {
- + ret= luaO_str2i(s,res_i,&endptr);
- + if (ret==0) return 0;
- + }
- + if (ret==TK_NUMBER) {
- + lua_assert(res_n);
- + /* Note: Visual C++ 2008 Express 'strtod()' does not read in "0x..."
- + * numbers; it will read '0' and spit 'x' as endptr.
- + * This means hex constants not fitting in 'lua_Integer' won't
- + * be read in at all. What to do?
- + */
- + *res_n = lua_str2real(s, &endptr);
- + if (endptr == s) return 0; /* conversion failed */
- + /* Visual C++ 2008 'strtod()' does not allow "0x..." input. */
- +#if defined(_MSC_VER) && !defined(LNUM_FLOAT) && !defined(LNUM_INT64)
- + if (*res_n==0 && *endptr=='x') {
- + /* Hex constant too big for 'lua_Integer' but that could fit in 'lua_Number'
- + * integer bits
- + */
- + unsigned __int64 v= _strtoui64( s, &endptr, 16 );
- + /* We just let > 64 bit values be clamped to _UI64_MAX (MSDN does not say 'errno'==ERANGE would be set) */
- + *res_n= cast_num(v);
- + if (*res_n != v) return 0; /* Would have lost accuracy */
- + }
- +#endif
- +#ifdef LNUM_COMPLEX
- + if (*endptr == 'i') { endptr++; ret= TK_NUMBER2; }
- +#endif
- + }
- + if (*endptr) {
- + while (isspace(cast(unsigned char, *endptr))) endptr++;
- + if (*endptr) return 0; /* invalid trail */
- + }
- + return ret;
- +}
- +
- +
- +/* Functions for finding out, when integer operations remain in range
- + * (and doing them).
- + */
- +int try_addint( lua_Integer *r, lua_Integer ib, lua_Integer ic ) {
- + lua_Integer v= ib+ic; /* may overflow */
- + if (ib>0 && ic>0) { if (v < 0) return 0; /*overflow, use floats*/ }
- + else if (ib<0 && ic<0) { if (v >= 0) return 0; }
- + *r= v;
- + return 1;
- +}
- +
- +int try_subint( lua_Integer *r, lua_Integer ib, lua_Integer ic ) {
- + lua_Integer v= ib-ic; /* may overflow */
- + if (ib>=0 && ic<0) { if (v < 0) return 0; /*overflow, use floats*/ }
- + else if (ib<0 && ic>0) { if (v >= 0) return 0; }
- + *r= v;
- + return 1;
- +}
- +
- +int try_mulint( lua_Integer *r, lua_Integer ib, lua_Integer ic ) {
- + if (ib!=LUA_INTEGER_MIN && ic!=LUA_INTEGER_MIN) {
- + lua_Integer b= luai_abs(ib), c= luai_abs(ic);
- + if ( (ib==0) || (LUA_INTEGER_MAX/b >= c) ) {
- + *r= ib*ic; /* no overflow */
- + return 1;
- + }
- + } else if (ib==0 || ic==0) {
- + *r= 0; return 1;
- + }
- +
- + /* Result can be LUA_INTEGER_MIN; if it is, calculating it using floating
- + * point will not cause accuracy loss.
- + */
- + if ( luai_nummul( cast_num(ib), cast_num(ic) ) == LUA_INTEGER_MIN ) {
- + *r= LUA_INTEGER_MIN;
- + return 1;
- + }
- + return 0;
- +}
- +
- +int try_divint( lua_Integer *r, lua_Integer ib, lua_Integer ic ) {
- + /* N/0: leave to float side, to give an error
- + */
- + if (ic==0) return 0;
- +
- + /* N/LUA_INTEGER_MIN: always non-integer results, or 0 or +1
- + */
- + if (ic==LUA_INTEGER_MIN) {
- + if (ib==LUA_INTEGER_MIN) { *r=1; return 1; }
- + if (ib==0) { *r=0; return 1; }
- +
- + /* LUA_INTEGER_MIN (-2^31|63)/N: calculate using float side (either the division
- + * causes non-integer results, or there is no accuracy loss in int->fp->int
- + * conversions (N=2,4,8,..,256 and N=2^30,2^29,..2^23).
- + */
- + } else if (ib==LUA_INTEGER_MIN) {
- + lua_Number d= luai_numdiv( cast_num(LUA_INTEGER_MIN), cast_num(ic) );
- + lua_Integer i; lua_number2integer(i,d);
- + if (cast_num(i)==d) { *r= i; return 1; }
- +
- + } else {
- + /* Note: We _can_ use ANSI C mod here, even on negative values, since
- + * we only test for == 0 (the sign would be implementation dependent).
- + */
- + if (ib%ic == 0) { *r= ib/ic; return 1; }
- + }
- +
- + return 0;
- +}
- +
- +int try_modint( lua_Integer *r, lua_Integer ib, lua_Integer ic ) {
- + if (ic!=0) {
- + /* ANSI C can be trusted when b%c==0, or when values are non-negative.
- + * b - (floor(b/c) * c)
- + * -->
- + * + +: b - (b/c) * c (b % c can be used)
- + * - -: b - (b/c) * c (b % c could work, but not defined by ANSI C)
- + * 0 -: b - (b/c) * c (=0, b % c could work, but not defined by ANSI C)
- + * - +: b - (b/c-1) * c (when b!=-c)
- + * + -: b - (b/c-1) * c (when b!=-c)
- + *
- + * o MIN%MIN ends up 0, via overflow in calcs but that does not matter.
- + * o MIN%MAX ends up MAX-1 (and other such numbers), also after overflow,
- + * but that does not matter, results do.
- + */
- + lua_Integer v= ib % ic;
- + if ( v!=0 && (ib<0 || ic<0) ) {
- + v= ib - ((ib/ic) - ((ib<=0 && ic<0) ? 0:1)) * ic;
- + }
- + /* Result should always have same sign as 2nd argument. (PIL2) */
- + lua_assert( (v<0) ? (ic<0) : (v>0) ? (ic>0) : 1 );
- + *r= v;
- + return 1;
- + }
- + return 0; /* let float side return NaN */
- +}
- +
- +int try_powint( lua_Integer *r, lua_Integer ib, lua_Integer ic ) {
- +
- + /* In FLOAT/INT32 or FLOAT|DOUBLE/INT64 modes, calculating integer powers
- + * via FP realm may lose accuracy (i.e. 7^11 = 1977326743, which fits int32
- + * but not 23-bit float mantissa).
- + *
- + * The current solution is dumb, but it works and uses little code. Use of
- + * integer powers is not anticipated to be very frequent (apart from 2^x,
- + * which is separately optimized).
- + */
- + if (ib==0) *r=0;
- + else if (ic<0) return 0; /* FP realm */
- + else if (ib==2 && ic < (int)sizeof(lua_Integer)*8-1) *r= ((lua_Integer)1)<<ic; /* 1,2,4,...2^30 | 2^62 optimization */
- + else if (ic==0) *r=1;
- + else if (luai_abs(ib)==1) *r= (ic%2) ? ib:1;
- + else {
- + lua_Integer x= ib;
- + while( --ic ) {
- + if (!try_mulint( &x, x, ib ))
- + return 0; /* FP realm */
- + }
- + *r= x;
- + }
- + return 1;
- +}
- +
- +int try_unmint( lua_Integer *r, lua_Integer ib ) {
- + /* Negating LUA_INTEGER_MIN leaves the range. */
- + if ( ib != LUA_INTEGER_MIN )
- + { *r= -ib; return 1; }
- + return 0;
- +}
- +
- --- /dev/null
- +++ b/src/lnum.h
- @@ -0,0 +1,116 @@
- +/*
- +** $Id: lnum.h,v ... $
- +** Internal Number model
- +** See Copyright Notice in lua.h
- +*/
- +
- +#ifndef lnum_h
- +#define lnum_h
- +
- +#include <math.h>
- +
- +#include "lobject.h"
- +
- +/*
- +** The luai_num* macros define the primitive operations over 'lua_Number's
- +** (not 'lua_Integer's, not 'lua_Complex').
- +*/
- +#define luai_numadd(a,b) ((a)+(b))
- +#define luai_numsub(a,b) ((a)-(b))
- +#define luai_nummul(a,b) ((a)*(b))
- +#define luai_numdiv(a,b) ((a)/(b))
- +#define luai_nummod(a,b) ((a) - _LF(floor)((a)/(b))*(b))
- +#define luai_numpow(a,b) (_LF(pow)(a,b))
- +#define luai_numunm(a) (-(a))
- +#define luai_numeq(a,b) ((a)==(b))
- +#define luai_numlt(a,b) ((a)<(b))
- +#define luai_numle(a,b) ((a)<=(b))
- +#define luai_numisnan(a) (!luai_numeq((a), (a)))
- +
- +int try_addint( lua_Integer *r, lua_Integer ib, lua_Integer ic );
- +int try_subint( lua_Integer *r, lua_Integer ib, lua_Integer ic );
- +int try_mulint( lua_Integer *r, lua_Integer ib, lua_Integer ic );
- +int try_divint( lua_Integer *r, lua_Integer ib, lua_Integer ic );
- +int try_modint( lua_Integer *r, lua_Integer ib, lua_Integer ic );
- +int try_powint( lua_Integer *r, lua_Integer ib, lua_Integer ic );
- +int try_unmint( lua_Integer *r, lua_Integer ib );
- +
- +#ifdef LNUM_COMPLEX
- + static inline lua_Complex luai_vectunm( lua_Complex a ) { return -a; }
- + static inline lua_Complex luai_vectadd( lua_Complex a, lua_Complex b ) { return a+b; }
- + static inline lua_Complex luai_vectsub( lua_Complex a, lua_Complex b ) { return a-b; }
- + static inline lua_Complex luai_vectmul( lua_Complex a, lua_Complex b ) { return a*b; }
- + static inline lua_Complex luai_vectdiv( lua_Complex a, lua_Complex b ) { return a/b; }
- +
- +/*
- + * C99 does not provide modulus for complex numbers. It most likely is not
- + * meaningful at all.
- + */
- +
- +/*
- + * Complex power
- + *
- + * C99 'cpow' gives inaccurate results for many common cases s.a. (1i)^2 ->
- + * -1+1.2246467991474e-16i (OS X 10.4, gcc 4.0.1 build 5367)
- + *
- + * [(a+bi)^(c+di)] = (r^c) * exp(-d*t) * cos(c*t + d*ln(r)) +
- + * = (r^c) * exp(-d*t) * sin(c*t + d*ln(r)) *i
- + * r = sqrt(a^2+b^2), t = arctan( b/a )
- + *
- + * Reference: <http://home.att.net/~srschmitt/complexnumbers.html>
- + * Could also be calculated using: x^y = exp(ln(x)*y)
- + *
- + * Note: Defined here (and not in .c) so 'lmathlib.c' can share the
- + * implementation.
- + */
- + static inline
- + lua_Complex luai_vectpow( lua_Complex a, lua_Complex b )
- + {
- +# if 1
- + lua_Number ar= _LF(creal)(a), ai= _LF(cimag)(a);
- + lua_Number br= _LF(creal)(b), bi= _LF(cimag)(b);
- +
- + if (ai==0 && bi==0) { /* a^c (real) */
- + return luai_numpow( ar, br );
- + }
- +
- + int br_int= (int)br;
- +
- + if ( ai!=0 && bi==0 && br_int==br && br_int!=0 && br_int!=INT_MIN ) {
- + /* (a+bi)^N, N = { +-1,+-2, ... +-INT_MAX }
- + */
- + lua_Number k= luai_numpow( _LF(sqrt) (ar*ar + ai*ai), br );
- + lua_Number cos_z, sin_z;
- +
- + /* Situation depends upon c (N) in the following manner:
- + *
- + * N%4==0 => cos(c*t)=1, sin(c*t)=0
- + * (N*sign(b))%4==1 or (N*sign(b))%4==-3 => cos(c*t)=0, sin(c*t)=1
- + * N%4==2 or N%4==-2 => cos(c*t)=-1, sin(c*t)=0
- + * (N*sign(b))%4==-1 or (N*sign(b))%4==3 => cos(c*t)=0, sin(c*t)=-1
- + */
- + int br_int_abs = br_int<0 ? -br_int:br_int;
- +
- + switch( (br_int_abs%4) * (br_int<0 ? -1:1) * (ai<0 ? -1:1) ) {
- + case 0: cos_z=1, sin_z=0; break;
- + case 2: case -2: cos_z=-1, sin_z=0; break;
- + case 1: case -3: cos_z=0, sin_z=1; break;
- + case 3: case -1: cos_z=0, sin_z=-1; break;
- + default: lua_assert(0); return 0;
- + }
- + return k*cos_z + (k*sin_z)*I;
- + }
- +# endif
- + return _LF(cpow) ( a, b );
- + }
- +#endif
- +
- +LUAI_FUNC int luaO_str2d (const char *s, lua_Number *res1, lua_Integer *res2);
- +LUAI_FUNC void luaO_num2buf( char *s, const TValue *o );
- +
- +LUAI_FUNC int /*bool*/ tt_integer_valued( const TValue *o, lua_Integer *ref );
- +
- +#define luai_normalize(o) \
- +{ lua_Integer _i; if (tt_integer_valued(o,&_i)) setivalue(o,_i); }
- +
- +#endif
- --- /dev/null
- +++ b/src/lnum_config.h
- @@ -0,0 +1,221 @@
- +/*
- +** $Id: lnum_config.h,v ... $
- +** Internal Number model
- +** See Copyright Notice in lua.h
- +*/
- +
- +#ifndef lnum_config_h
- +#define lnum_config_h
- +
- +/*
- +** Default number modes
- +*/
- +#if (!defined LNUM_DOUBLE) && (!defined LNUM_FLOAT) && (!defined LNUM_LDOUBLE)
- +# define LNUM_FLOAT
- +#endif
- +#if (!defined LNUM_INT16) && (!defined LNUM_INT32) && (!defined LNUM_INT64)
- +# define LNUM_INT32
- +#endif
- +
- +/*
- +** Require C99 mode for COMPLEX, FLOAT and LDOUBLE (only DOUBLE is ANSI C).
- +*/
- +#if defined(LNUM_COMPLEX) && (__STDC_VERSION__ < 199901L)
- +# error "Need C99 for complex (use '--std=c99' or similar)"
- +#elif defined(LNUM_LDOUBLE) && (__STDC_VERSION__ < 199901L) && !defined(_MSC_VER)
- +# error "Need C99 for 'long double' (use '--std=c99' or similar)"
- +#elif defined(LNUM_FLOAT) && (__STDC_VERSION__ < 199901L)
- +/* LNUM_FLOAT not supported on Windows */
- +# error "Need C99 for 'float' (use '--std=c99' or similar)"
- +#endif
- +
- +/*
- +** Number mode identifier to accompany the version string.
- +*/
- +#ifdef LNUM_COMPLEX
- +# define _LNUM1 "complex "
- +#else
- +# define _LNUM1 ""
- +#endif
- +#ifdef LNUM_DOUBLE
- +# define _LNUM2 "double"
- +#elif defined(LNUM_FLOAT)
- +# define _LNUM2 "float"
- +#elif defined(LNUM_LDOUBLE)
- +# define _LNUM2 "ldouble"
- +#endif
- +#ifdef LNUM_INT32
- +# define _LNUM3 "int32"
- +#elif defined(LNUM_INT64)
- +# define _LNUM3 "int64"
- +#elif defined(LNUM_INT16)
- +# define _LNUM3 "int16"
- +#endif
- +#define LUA_LNUM _LNUM1 _LNUM2 " " _LNUM3
- +
- +/*
- +** LUA_NUMBER is the type of floating point number in Lua
- +** LUA_NUMBER_SCAN is the format for reading numbers.
- +** LUA_NUMBER_FMT is the format for writing numbers.
- +*/
- +#ifdef LNUM_FLOAT
- +# define LUA_NUMBER float
- +# define LUA_NUMBER_SCAN "%f"
- +# define LUA_NUMBER_FMT "%g"
- +#elif (defined LNUM_DOUBLE)
- +# define LUA_NUMBER double
- +# define LUA_NUMBER_SCAN "%lf"
- +# define LUA_NUMBER_FMT "%.14g"
- +#elif (defined LNUM_LDOUBLE)
- +# define LUA_NUMBER long double
- +# define LUA_NUMBER_SCAN "%Lg"
- +# define LUA_NUMBER_FMT "%.20Lg"
- +#endif
- +
- +
- +/*
- +** LUAI_MAXNUMBER2STR: size of a buffer fitting any number->string result.
- +**
- +** double: 24 (sign, x.xxxxxxxxxxxxxxe+nnnn, and \0)
- +** int64: 21 (19 digits, sign, and \0)
- +** long double: 43 for 128-bit (sign, x.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxe+nnnn, and \0)
- +** 30 for 80-bit (sign, x.xxxxxxxxxxxxxxxxxxxxe+nnnn, and \0)
- +*/
- +#ifdef LNUM_LDOUBLE
- +# define _LUAI_MN2S 44
- +#else
- +# define _LUAI_MN2S 24
- +#endif
- +
- +#ifdef LNUM_COMPLEX
- +# define LUAI_MAXNUMBER2STR (2*_LUAI_MN2S)
- +#else
- +# define LUAI_MAXNUMBER2STR _LUAI_MN2S
- +#endif
- +
- +/*
- +** LUA_INTEGER is the integer type used by lua_pushinteger/lua_tointeger/lua_isinteger.
- +** LUA_INTEGER_SCAN is the format for reading integers
- +** LUA_INTEGER_FMT is the format for writing integers
- +**
- +** Note: Visual C++ 2005 does not have 'strtoull()', use '_strtoui64()' instead.
- +*/
- +#ifdef LNUM_INT32
- +# if LUAI_BITSINT > 16
- +# define LUA_INTEGER int
- +# define LUA_INTEGER_SCAN "%d"
- +# define LUA_INTEGER_FMT "%d"
- +# else
- +/* Note: 'LUA_INTEGER' being 'ptrdiff_t' (as in Lua 5.1) causes problems with
- + * 'printf()' operations. Also 'unsigned ptrdiff_t' is invalid.
- + */
- +# define LUA_INTEGER long
- +# define LUA_INTEGER_SCAN "%ld"
- +# define LUA_INTEGER_FMT "%ld"
- +# endif
- +# define LUA_INTEGER_MAX 0x7FFFFFFF /* 2^31-1 */
- +/* */
- +#elif defined(LNUM_INT64)
- +# define LUA_INTEGER long long
- +# ifdef _MSC_VER
- +# define lua_str2ul _strtoui64
- +# else
- +# define lua_str2ul strtoull
- +# endif
- +# define LUA_INTEGER_SCAN "%lld"
- +# define LUA_INTEGER_FMT "%lld"
- +# define LUA_INTEGER_MAX 0x7fffffffffffffffLL /* 2^63-1 */
- +# define LUA_INTEGER_MIN (-LUA_INTEGER_MAX - 1LL) /* -2^63 */
- +/* */
- +#elif defined(LNUM_INT16)
- +# if LUAI_BITSINT > 16
- +# define LUA_INTEGER short
- +# define LUA_INTEGER_SCAN "%hd"
- +# define LUA_INTEGER_FMT "%hd"
- +# else
- +# define LUA_INTEGER int
- +# define LUA_INTEGER_SCAN "%d"
- +# define LUA_INTEGER_FMT "%d"
- +# endif
- +# define LUA_INTEGER_MAX 0x7FFF /* 2^16-1 */
- +#endif
- +
- +#ifndef lua_str2ul
- +# define lua_str2ul (unsigned LUA_INTEGER)strtoul
- +#endif
- +#ifndef LUA_INTEGER_MIN
- +# define LUA_INTEGER_MIN (-LUA_INTEGER_MAX -1) /* -2^16|32 */
- +#endif
- +
- +/*
- +@@ lua_number2int is a macro to convert lua_Number to int.
- +@@ lua_number2integer is a macro to convert lua_Number to lua_Integer.
- +** 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.
- +*/
- +
- +/* On a Pentium, resort to a trick */
- +#if defined(LNUM_DOUBLE) && !defined(LUA_ANSI) && !defined(__SSE2__) && \
- + (defined(__i386) || defined (_M_IX86) || defined(__i386__))
- +
- +/* On a Microsoft compiler, use assembler */
- +# if defined(_MSC_VER)
- +# define lua_number2int(i,d) __asm fld d __asm fistp i
- +# else
- +
- +/* the next trick should work on any Pentium, but sometimes clashes
- + with a DirectX idiosyncrasy */
- +union luai_Cast { double l_d; long l_l; };
- +# define lua_number2int(i,d) \
- + { volatile union luai_Cast u; u.l_d = (d) + 6755399441055744.0; (i) = u.l_l; }
- +# endif
- +
- +# ifndef LNUM_INT64
- +# define lua_number2integer lua_number2int
- +# endif
- +
- +/* this option always works, but may be slow */
- +#else
- +# define lua_number2int(i,d) ((i)=(int)(d))
- +#endif
- +
- +/* Note: Some compilers (OS X gcc 4.0?) may choke on double->long long conversion
- + * since it can lose precision. Others do require 'long long' there.
- + */
- +#ifndef lua_number2integer
- +# define lua_number2integer(i,d) ((i)=(lua_Integer)(d))
- +#endif
- +
- +/*
- +** 'luai_abs()' to give absolute value of 'lua_Integer'
- +*/
- +#ifdef LNUM_INT32
- +# define luai_abs abs
- +#elif defined(LNUM_INT64) && (__STDC_VERSION__ >= 199901L)
- +# define luai_abs llabs
- +#else
- +# define luai_abs(v) ((v) >= 0 ? (v) : -(v))
- +#endif
- +
- +/*
- +** LUAI_UACNUMBER is the result of an 'usual argument conversion' over a number.
- +** LUAI_UACINTEGER the same, over an integer.
- +*/
- +#define LUAI_UACNUMBER double
- +#define LUAI_UACINTEGER long
- +
- +/* ANSI C only has math funcs for 'double. C99 required for float and long double
- + * variants.
- + */
- +#ifdef LNUM_DOUBLE
- +# define _LF(name) name
- +#elif defined(LNUM_FLOAT)
- +# define _LF(name) name ## f
- +#elif defined(LNUM_LDOUBLE)
- +# define _LF(name) name ## l
- +#endif
- +
- +#endif
- +
- --- a/src/lobject.c
- +++ b/src/lobject.c
- @@ -21,7 +21,8 @@
- #include "lstate.h"
- #include "lstring.h"
- #include "lvm.h"
- -
- +#include "llex.h"
- +#include "lnum.h"
-
-
- const TValue luaO_nilobject_ = {{NULL}, LUA_TNIL};
- @@ -70,12 +71,31 @@ int luaO_log2 (unsigned int x) {
-
-
- int luaO_rawequalObj (const TValue *t1, const TValue *t2) {
- - if (ttype(t1) != ttype(t2)) return 0;
- + if (!ttype_ext_same(t1,t2)) return 0;
- else switch (ttype(t1)) {
- case LUA_TNIL:
- return 1;
- + case LUA_TINT:
- + if (ttype(t2)==LUA_TINT)
- + return ivalue(t1) == ivalue(t2);
- + else { /* t1:int, t2:num */
- +#ifdef LNUM_COMPLEX
- + if (nvalue_img_fast(t2) != 0) return 0;
- +#endif
- + /* Avoid doing accuracy losing cast, if possible. */
- + lua_Integer tmp;
- + if (tt_integer_valued(t2,&tmp))
- + return ivalue(t1) == tmp;
- + else
- + return luai_numeq( cast_num(ivalue(t1)), nvalue_fast(t2) );
- + }
- case LUA_TNUMBER:
- - return luai_numeq(nvalue(t1), nvalue(t2));
- + if (ttype(t2)==LUA_TINT)
- + return luaO_rawequalObj(t2, t1); /* swap LUA_TINT to left */
- +#ifdef LNUM_COMPLEX
- + if (!luai_numeq(nvalue_img_fast(t1), nvalue_img_fast(t2))) return 0;
- +#endif
- + return luai_numeq(nvalue_fast(t1), nvalue_fast(t2));
- case LUA_TBOOLEAN:
- return bvalue(t1) == bvalue(t2); /* boolean true must be 1 !! */
- case LUA_TLIGHTUSERDATA:
- @@ -86,21 +106,6 @@ int luaO_rawequalObj (const TValue *t1,
- }
- }
-
- -
- -int luaO_str2d (const char *s, lua_Number *result) {
- - char *endptr;
- - *result = lua_str2number(s, &endptr);
- - if (endptr == s) return 0; /* conversion failed */
- - if (*endptr == 'x' || *endptr == 'X') /* maybe an hexadecimal constant? */
- - *result = cast_num(strtoul(s, &endptr, 16));
- - if (*endptr == '\0') return 1; /* most common case */
- - while (isspace(cast(unsigned char, *endptr))) endptr++;
- - if (*endptr != '\0') return 0; /* invalid trailing characters? */
- - return 1;
- -}
- -
- -
- -
- static void pushstr (lua_State *L, const char *str) {
- setsvalue2s(L, L->top, luaS_new(L, str));
- incr_top(L);
- @@ -131,7 +136,11 @@ const char *luaO_pushvfstring (lua_State
- break;
- }
- case 'd': {
- - setnvalue(L->top, cast_num(va_arg(argp, int)));
- + /* This is tricky for 64-bit integers; maybe they even cannot be
- + * supported on all compilers; depends on the conversions applied to
- + * variable argument lists. TBD: test!
- + */
- + setivalue(L->top, (lua_Integer) va_arg(argp, l_uacInteger));
- incr_top(L);
- break;
- }
- @@ -212,3 +221,4 @@ void luaO_chunkid (char *out, const char
- }
- }
- }
- +
- --- a/src/lobject.h
- +++ b/src/lobject.h
- @@ -17,7 +17,11 @@
-
-
- /* tags for values visible from Lua */
- -#define LAST_TAG LUA_TTHREAD
- +#if LUA_TINT > LUA_TTHREAD
- +# define LAST_TAG LUA_TINT
- +#else
- +# define LAST_TAG LUA_TTHREAD
- +#endif
-
- #define NUM_TAGS (LAST_TAG+1)
-
- @@ -59,7 +63,12 @@ typedef struct GCheader {
- typedef union {
- GCObject *gc;
- void *p;
- +#ifdef LNUM_COMPLEX
- + lua_Complex n;
- +#else
- lua_Number n;
- +#endif
- + lua_Integer i;
- int b;
- } Value;
-
- @@ -77,7 +86,11 @@ typedef struct lua_TValue {
-
- /* Macros to test type */
- #define ttisnil(o) (ttype(o) == LUA_TNIL)
- -#define ttisnumber(o) (ttype(o) == LUA_TNUMBER)
- +#define ttisint(o) (ttype(o) == LUA_TINT)
- +#define ttisnumber(o) ((ttype(o) == LUA_TINT) || (ttype(o) == LUA_TNUMBER))
- +#ifdef LNUM_COMPLEX
- +# define ttiscomplex(o) ((ttype(o) == LUA_TNUMBER) && (nvalue_img_fast(o)!=0))
- +#endif
- #define ttisstring(o) (ttype(o) == LUA_TSTRING)
- #define ttistable(o) (ttype(o) == LUA_TTABLE)
- #define ttisfunction(o) (ttype(o) == LUA_TFUNCTION)
- @@ -90,7 +103,25 @@ typedef struct lua_TValue {
- #define ttype(o) ((o)->tt)
- #define gcvalue(o) check_exp(iscollectable(o), (o)->value.gc)
- #define pvalue(o) check_exp(ttislightuserdata(o), (o)->value.p)
- -#define nvalue(o) check_exp(ttisnumber(o), (o)->value.n)
- +
- +#define ttype_ext(o) ( ttype(o) == LUA_TINT ? LUA_TNUMBER : ttype(o) )
- +#define ttype_ext_same(o1,o2) ( (ttype(o1)==ttype(o2)) || (ttisnumber(o1) && ttisnumber(o2)) )
- +
- +/* '_fast' variants are for cases where 'ttype(o)' is known to be LUA_TNUMBER.
- + */
- +#ifdef LNUM_COMPLEX
- +# define nvalue_complex_fast(o) check_exp( ttype(o)==LUA_TNUMBER, (o)->value.n )
- +# define nvalue_fast(o) ( _LF(creal) ( nvalue_complex_fast(o) ) )
- +# define nvalue_img_fast(o) ( _LF(cimag) ( nvalue_complex_fast(o) ) )
- +# define nvalue_complex(o) check_exp( ttisnumber(o), (ttype(o)==LUA_TINT) ? (o)->value.i : (o)->value.n )
- +# define nvalue_img(o) check_exp( ttisnumber(o), (ttype(o)==LUA_TINT) ? 0 : _LF(cimag)( (o)->value.n ) )
- +# define nvalue(o) check_exp( ttisnumber(o), (ttype(o)==LUA_TINT) ? cast_num((o)->value.i) : _LF(creal)((o)->value.n) )
- +#else
- +# define nvalue(o) check_exp( ttisnumber(o), (ttype(o)==LUA_TINT) ? cast_num((o)->value.i) : (o)->value.n )
- +# define nvalue_fast(o) check_exp( ttype(o)==LUA_TNUMBER, (o)->value.n )
- +#endif
- +#define ivalue(o) check_exp( ttype(o)==LUA_TINT, (o)->value.i )
- +
- #define rawtsvalue(o) check_exp(ttisstring(o), &(o)->value.gc->ts)
- #define tsvalue(o) (&rawtsvalue(o)->tsv)
- #define rawuvalue(o) check_exp(ttisuserdata(o), &(o)->value.gc->u)
- @@ -116,8 +147,27 @@ typedef struct lua_TValue {
- /* Macros to set values */
- #define setnilvalue(obj) ((obj)->tt=LUA_TNIL)
-
- -#define setnvalue(obj,x) \
- - { TValue *i_o=(obj); i_o->value.n=(x); i_o->tt=LUA_TNUMBER; }
- +/* Must not have side effects, 'x' may be expression.
- +*/
- +#define setivalue(obj,x) \
- + { TValue *i_o=(obj); i_o->value.i=(x); i_o->tt=LUA_TINT; }
- +
- +# define setnvalue(obj,x) \
- + { TValue *i_o=(obj); i_o->value.n= (x); i_o->tt=LUA_TNUMBER; }
- +
- +/* Note: Complex always has "inline", both are C99.
- +*/
- +#ifdef LNUM_COMPLEX
- + static inline void setnvalue_complex_fast( TValue *obj, lua_Complex x ) {
- + lua_assert( _LF(cimag)(x) != 0 );
- + obj->value.n= x; obj->tt= LUA_TNUMBER;
- + }
- + static inline void setnvalue_complex( TValue *obj, lua_Complex x ) {
- + if (_LF(cimag)(x) == 0) { setnvalue(obj, _LF(creal)(x)); }
- + else { obj->value.n= x; obj->tt= LUA_TNUMBER; }
- + }
- +#endif
- +
-
- #define setpvalue(obj,x) \
- { TValue *i_o=(obj); i_o->value.p=(x); i_o->tt=LUA_TLIGHTUSERDATA; }
- @@ -155,9 +205,6 @@ typedef struct lua_TValue {
- i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TPROTO; \
- checkliveness(G(L),i_o); }
-
- -
- -
- -
- #define setobj(L,obj1,obj2) \
- { const TValue *o2=(obj2); TValue *o1=(obj1); \
- o1->value = o2->value; o1->tt=o2->tt; \
- @@ -185,8 +232,11 @@ typedef struct lua_TValue {
-
- #define setttype(obj, tt) (ttype(obj) = (tt))
-
- -
- -#define iscollectable(o) (ttype(o) >= LUA_TSTRING)
- +#if LUA_TINT >= LUA_TSTRING
- +# define iscollectable(o) ((ttype(o) >= LUA_TSTRING) && (ttype(o) != LUA_TINT))
- +#else
- +# define iscollectable(o) (ttype(o) >= LUA_TSTRING)
- +#endif
-
-
-
- @@ -370,12 +420,10 @@ LUAI_FUNC int luaO_log2 (unsigned int x)
- LUAI_FUNC int luaO_int2fb (unsigned int x);
- LUAI_FUNC int luaO_fb2int (int x);
- LUAI_FUNC int luaO_rawequalObj (const TValue *t1, const TValue *t2);
- -LUAI_FUNC int luaO_str2d (const char *s, lua_Number *result);
- LUAI_FUNC const char *luaO_pushvfstring (lua_State *L, const char *fmt,
- va_list argp);
- LUAI_FUNC const char *luaO_pushfstring (lua_State *L, const char *fmt, ...);
- LUAI_FUNC void luaO_chunkid (char *out, const char *source, size_t len);
-
- -
- #endif
-
- --- a/src/loslib.c
- +++ b/src/loslib.c
- @@ -186,15 +186,30 @@ static int os_time (lua_State *L) {
- }
- if (t == (time_t)(-1))
- lua_pushnil(L);
- - else
- - lua_pushnumber(L, (lua_Number)t);
- + else {
- + /* On float systems the pushed value must be an integer, NOT a number.
- + * Otherwise, accuracy is lost in the time_t->float conversion.
- + */
- +#ifdef LNUM_FLOAT
- + lua_pushinteger(L, (lua_Integer) t);
- +#else
- + lua_pushnumber(L, (lua_Number) t);
- +#endif
- + }
- return 1;
- }
-
-
- static int os_difftime (lua_State *L) {
- +#ifdef LNUM_FLOAT
- + lua_Integer i= (lua_Integer)
- + difftime( (time_t)(luaL_checkinteger(L, 1)),
- + (time_t)(luaL_optinteger(L, 2, 0)));
- + lua_pushinteger(L, i);
- +#else
- lua_pushnumber(L, difftime((time_t)(luaL_checknumber(L, 1)),
- (time_t)(luaL_optnumber(L, 2, 0))));
- +#endif
- return 1;
- }
-
- --- a/src/lparser.c
- +++ b/src/lparser.c
- @@ -33,7 +33,6 @@
-
- #define luaY_checklimit(fs,v,l,m) if ((v)>(l)) errorlimit(fs,l,m)
-
- -
- /*
- ** nodes for block list (list of active blocks)
- */
- @@ -72,7 +71,7 @@ static void errorlimit (FuncState *fs, i
- const char *msg = (fs->f->linedefined == 0) ?
- luaO_pushfstring(fs->L, "main function has more than %d %s", limit, what) :
- luaO_pushfstring(fs->L, "function at line %d has more than %d %s",
- - fs->f->linedefined, limit, what);
- + (fs->f->linedefined), limit, what);
- luaX_lexerror(fs->ls, msg, 0);
- }
-
- @@ -733,6 +732,18 @@ static void simpleexp (LexState *ls, exp
- v->u.nval = ls->t.seminfo.r;
- break;
- }
- + case TK_INT: {
- + init_exp(v, VKINT, 0);
- + v->u.ival = ls->t.seminfo.i;
- + break;
- + }
- +#ifdef LNUM_COMPLEX
- + case TK_NUMBER2: {
- + init_exp(v, VKNUM2, 0);
- + v->u.nval = ls->t.seminfo.r;
- + break;
- + }
- +#endif
- case TK_STRING: {
- codestring(ls, v, ls->t.seminfo.ts);
- break;
- @@ -1079,7 +1090,7 @@ static void fornum (LexState *ls, TStrin
- if (testnext(ls, ','))
- exp1(ls); /* optional step */
- else { /* default step = 1 */
- - luaK_codeABx(fs, OP_LOADK, fs->freereg, luaK_numberK(fs, 1));
- + luaK_codeABx(fs, OP_LOADK, fs->freereg, luaK_integerK(fs, 1));
- luaK_reserveregs(fs, 1);
- }
- forbody(ls, base, line, 1, 1);
- --- a/src/lparser.h
- +++ b/src/lparser.h
- @@ -31,7 +31,11 @@ typedef enum {
- VRELOCABLE, /* info = instruction pc */
- VNONRELOC, /* info = result register */
- VCALL, /* info = instruction pc */
- - VVARARG /* info = instruction pc */
- + VVARARG, /* info = instruction pc */
- + VKINT /* ival = integer value */
- +#ifdef LNUM_COMPLEX
- + ,VKNUM2 /* nval = imaginary value */
- +#endif
- } expkind;
-
- typedef struct expdesc {
- @@ -39,6 +43,7 @@ typedef struct expdesc {
- union {
- struct { int info, aux; } s;
- lua_Number nval;
- + lua_Integer ival;
- } u;
- int t; /* patch list of `exit when true' */
- int f; /* patch list of `exit when false' */
- --- a/src/lstrlib.c
- +++ b/src/lstrlib.c
- @@ -43,8 +43,8 @@ static ptrdiff_t posrelat (ptrdiff_t pos
- static int str_sub (lua_State *L) {
- size_t l;
- const char *s = luaL_checklstring(L, 1, &l);
- - ptrdiff_t start = posrelat(luaL_checkinteger(L, 2), l);
- - ptrdiff_t end = posrelat(luaL_optinteger(L, 3, -1), l);
- + ptrdiff_t start = posrelat(luaL_checkint32(L, 2), l);
- + ptrdiff_t end = posrelat(luaL_optint32(L, 3, -1), l);
- if (start < 1) start = 1;
- if (end > (ptrdiff_t)l) end = (ptrdiff_t)l;
- if (start <= end)
- @@ -106,8 +106,8 @@ static int str_rep (lua_State *L) {
- static int str_byte (lua_State *L) {
- size_t l;
- const char *s = luaL_checklstring(L, 1, &l);
- - ptrdiff_t posi = posrelat(luaL_optinteger(L, 2, 1), l);
- - ptrdiff_t pose = posrelat(luaL_optinteger(L, 3, posi), l);
- + ptrdiff_t posi = posrelat(luaL_optint32(L, 2, 1), l);
- + ptrdiff_t pose = posrelat(luaL_optint32(L, 3, posi), l);
- int n, i;
- if (posi <= 0) posi = 1;
- if ((size_t)pose > l) pose = l;
- @@ -496,7 +496,7 @@ static int str_find_aux (lua_State *L, i
- size_t l1, l2;
- const char *s = luaL_checklstring(L, 1, &l1);
- const char *p = luaL_checklstring(L, 2, &l2);
- - ptrdiff_t init = posrelat(luaL_optinteger(L, 3, 1), l1) - 1;
- + ptrdiff_t init = posrelat(luaL_optint32(L, 3, 1), l1) - 1;
- if (init < 0) init = 0;
- else if ((size_t)(init) > l1) init = (ptrdiff_t)l1;
- if (find && (lua_toboolean(L, 4) || /* explicit request? */
- @@ -690,7 +690,7 @@ static int str_gsub (lua_State *L) {
- ** maximum size of each format specification (such as '%-099.99d')
- ** (+10 accounts for %99.99x plus margin of error)
- */
- -#define MAX_FORMAT (sizeof(FLAGS) + sizeof(LUA_INTFRMLEN) + 10)
- +#define MAX_FORMAT (sizeof(FLAGS) + sizeof(LUA_INTEGER_FMT)-2 + 10)
-
-
- static void addquoted (lua_State *L, luaL_Buffer *b, int arg) {
- @@ -747,9 +747,9 @@ static const char *scanformat (lua_State
- static void addintlen (char *form) {
- size_t l = strlen(form);
- char spec = form[l - 1];
- - strcpy(form + l - 1, LUA_INTFRMLEN);
- - form[l + sizeof(LUA_INTFRMLEN) - 2] = spec;
- - form[l + sizeof(LUA_INTFRMLEN) - 1] = '\0';
- + const char *tmp= LUA_INTEGER_FMT; /* "%lld" or "%ld" */
- + strcpy(form + l - 1, tmp+1);
- + form[l + sizeof(LUA_INTEGER_FMT)-4] = spec;
- }
-
-
- @@ -779,12 +779,12 @@ static int str_format (lua_State *L) {
- }
- case 'd': case 'i': {
- addintlen(form);
- - sprintf(buff, form, (LUA_INTFRM_T)luaL_checknumber(L, arg));
- + sprintf(buff, form, luaL_checkinteger(L, arg));
- break;
- }
- case 'o': case 'u': case 'x': case 'X': {
- addintlen(form);
- - sprintf(buff, form, (unsigned LUA_INTFRM_T)luaL_checknumber(L, arg));
- + sprintf(buff, form, (unsigned LUA_INTEGER)luaL_checkinteger(L, arg));
- break;
- }
- case 'e': case 'E': case 'f':
- --- a/src/ltable.c
- +++ b/src/ltable.c
- @@ -33,6 +33,7 @@
- #include "lobject.h"
- #include "lstate.h"
- #include "ltable.h"
- +#include "lnum.h"
-
-
- /*
- @@ -51,25 +52,15 @@
-
- #define hashstr(t,str) hashpow2(t, (str)->tsv.hash)
- #define hashboolean(t,p) hashpow2(t, p)
- -
- +#define hashint(t,i) hashpow2(t,i)
-
- /*
- ** for some types, it is better to avoid modulus by power of 2, as
- ** they tend to have many 2 factors.
- */
- #define hashmod(t,n) (gnode(t, ((n) % ((sizenode(t)-1)|1))))
- -
- -
- #define hashpointer(t,p) hashmod(t, IntPoint(p))
-
- -
- -/*
- -** number of ints inside a lua_Number
- -*/
- -#define numints cast_int(sizeof(lua_Number)/sizeof(int))
- -
- -
- -
- #define dummynode (&dummynode_)
-
- static const Node dummynode_ = {
- @@ -80,27 +71,46 @@ static const Node dummynode_ = {
-
- /*
- ** hash for lua_Numbers
- +**
- +** for non-complex modes, never called with 'lua_Integer' value range (s.a. 0)
- */
- static Node *hashnum (const Table *t, lua_Number n) {
- - unsigned int a[numints];
- - int i;
- - if (luai_numeq(n, 0)) /* avoid problems with -0 */
- - return gnode(t, 0);
- - memcpy(a, &n, sizeof(a));
- - for (i = 1; i < numints; i++) a[0] += a[i];
- - return hashmod(t, a[0]);
- + const unsigned int *p= cast(const unsigned int *,&n);
- + unsigned int sum= *p;
- + unsigned int m= sizeof(lua_Number)/sizeof(int);
- + unsigned int i;
- + /* OS X Intel has 'm'==4 and gives "Bus error" if the last integer of
- + * 'n' is read; the actual size of long double is only 80 bits = 10 bytes.
- + * Linux x86 has 'm'==3, and does not require reduction.
- + */
- +#if defined(LNUM_LDOUBLE) && defined(__i386__)
- + if (m>3) m--;
- +#endif
- + for (i = 1; i < m; i++) sum += p[i];
- + return hashmod(t, sum);
- }
-
-
- -
- /*
- ** returns the `main' position of an element in a table (that is, the index
- ** of its hash value)
- +**
- +** Floating point numbers with integer value give the hash position of the
- +** integer (so they use the same table position).
- */
- static Node *mainposition (const Table *t, const TValue *key) {
- + lua_Integer i;
- switch (ttype(key)) {
- case LUA_TNUMBER:
- - return hashnum(t, nvalue(key));
- + if (tt_integer_valued(key,&i))
- + return hashint(t, i);
- +#ifdef LNUM_COMPLEX
- + if (nvalue_img_fast(key)!=0 && luai_numeq(nvalue_fast(key),0))
- + return gnode(t, 0); /* 0 and -0 to give same hash */
- +#endif
- + return hashnum(t, nvalue_fast(key));
- + case LUA_TINT:
- + return hashint(t, ivalue(key));
- case LUA_TSTRING:
- return hashstr(t, rawtsvalue(key));
- case LUA_TBOOLEAN:
- @@ -116,16 +126,20 @@ static Node *mainposition (const Table *
- /*
- ** returns the index for `key' if `key' is an appropriate key to live in
- ** the array part of the table, -1 otherwise.
- +**
- +** Anything <=0 is taken as not being in the array part.
- */
- -static int arrayindex (const TValue *key) {
- - if (ttisnumber(key)) {
- - lua_Number n = nvalue(key);
- - int k;
- - lua_number2int(k, n);
- - if (luai_numeq(cast_num(k), n))
- - return k;
- +static int arrayindex (const TValue *key, int max) {
- + lua_Integer k;
- + switch( ttype(key) ) {
- + case LUA_TINT:
- + k= ivalue(key); break;
- + case LUA_TNUMBER:
- + if (tt_integer_valued(key,&k)) break;
- + default:
- + return -1; /* not to be used as array index */
- }
- - return -1; /* `key' did not match some condition */
- + return ((k>0) && (k <= max)) ? cast_int(k) : -1;
- }
-
-
- @@ -137,8 +151,8 @@ static int arrayindex (const TValue *key
- static int findindex (lua_State *L, Table *t, StkId key) {
- int i;
- if (ttisnil(key)) return -1; /* first iteration */
- - i = arrayindex(key);
- - if (0 < i && i <= t->sizearray) /* is `key' inside array part? */
- + i = arrayindex(key, t->sizearray);
- + if (i>0) /* inside array part? */
- return i-1; /* yes; that's the index (corrected to C) */
- else {
- Node *n = mainposition(t, key);
- @@ -163,7 +177,7 @@ int luaH_next (lua_State *L, Table *t, S
- int i = findindex(L, t, key); /* find original element */
- for (i++; i < t->sizearray; i++) { /* try first array part */
- if (!ttisnil(&t->array[i])) { /* a non-nil value? */
- - setnvalue(key, cast_num(i+1));
- + setivalue(key, i+1);
- setobj2s(L, key+1, &t->array[i]);
- return 1;
- }
- @@ -209,8 +223,8 @@ static int computesizes (int nums[], int
-
-
- static int countint (const TValue *key, int *nums) {
- - int k = arrayindex(key);
- - if (0 < k && k <= MAXASIZE) { /* is `key' an appropriate array index? */
- + int k = arrayindex(key,MAXASIZE);
- + if (k>0) { /* appropriate array index? */
- nums[ceillog2(k)]++; /* count as such */
- return 1;
- }
- @@ -308,7 +322,7 @@ static void resize (lua_State *L, Table
- /* re-insert elements from vanishing slice */
- for (i=nasize; i<oldasize; i++) {
- if (!ttisnil(&t->array[i]))
- - setobjt2t(L, luaH_setnum(L, t, i+1), &t->array[i]);
- + setobjt2t(L, luaH_setint(L, t, i+1), &t->array[i]);
- }
- /* shrink array */
- luaM_reallocvector(L, t->array, oldasize, nasize, TValue);
- @@ -409,7 +423,9 @@ static TValue *newkey (lua_State *L, Tab
- othern = mainposition(t, key2tval(mp));
- if (othern != mp) { /* is colliding node out of its main position? */
- /* yes; move colliding node into free position */
- - while (gnext(othern) != mp) othern = gnext(othern); /* find previous */
- + while (gnext(othern) != mp) {
- + othern = gnext(othern); /* find previous */
- + }
- gnext(othern) = n; /* redo the chain with `n' in place of `mp' */
- *n = *mp; /* copy colliding node into free pos. (mp->next also goes) */
- gnext(mp) = NULL; /* now `mp' is free */
- @@ -432,17 +448,18 @@ static TValue *newkey (lua_State *L, Tab
- /*
- ** search function for integers
- */
- -const TValue *luaH_getnum (Table *t, int key) {
- +const TValue *luaH_getint (Table *t, lua_Integer key) {
- /* (1 <= key && key <= t->sizearray) */
- if (cast(unsigned int, key-1) < cast(unsigned int, t->sizearray))
- return &t->array[key-1];
- else {
- - lua_Number nk = cast_num(key);
- - Node *n = hashnum(t, nk);
- + Node *n = hashint(t, key);
- do { /* check whether `key' is somewhere in the chain */
- - if (ttisnumber(gkey(n)) && luai_numeq(nvalue(gkey(n)), nk))
- + if (ttisint(gkey(n)) && (ivalue(gkey(n)) == key)) {
- return gval(n); /* that's it */
- - else n = gnext(n);
- + } else {
- + n = gnext(n);
- + }
- } while (n);
- return luaO_nilobject;
- }
- @@ -470,14 +487,12 @@ const TValue *luaH_get (Table *t, const
- switch (ttype(key)) {
- case LUA_TNIL: return luaO_nilobject;
- case LUA_TSTRING: return luaH_getstr(t, rawtsvalue(key));
- + case LUA_TINT: return luaH_getint(t, ivalue(key));
- case LUA_TNUMBER: {
- - int k;
- - lua_Number n = nvalue(key);
- - lua_number2int(k, n);
- - if (luai_numeq(cast_num(k), nvalue(key))) /* index is int? */
- - return luaH_getnum(t, k); /* use specialized version */
- - /* else go through */
- - }
- + lua_Integer i;
- + if (tt_integer_valued(key,&i))
- + return luaH_getint(t,i);
- + } /* pass through */
- default: {
- Node *n = mainposition(t, key);
- do { /* check whether `key' is somewhere in the chain */
- @@ -498,20 +513,25 @@ TValue *luaH_set (lua_State *L, Table *t
- return cast(TValue *, p);
- else {
- if (ttisnil(key)) luaG_runerror(L, "table index is nil");
- - else if (ttisnumber(key) && luai_numisnan(nvalue(key)))
- - luaG_runerror(L, "table index is NaN");
- + else if (ttype(key)==LUA_TNUMBER) {
- + lua_Integer k;
- + if (luai_numisnan(nvalue_fast(key)))
- + luaG_runerror(L, "table index is NaN");
- + if (tt_integer_valued(key,&k))
- + return luaH_setint(L, t, k);
- + }
- return newkey(L, t, key);
- }
- }
-
-
- -TValue *luaH_setnum (lua_State *L, Table *t, int key) {
- - const TValue *p = luaH_getnum(t, key);
- +TValue *luaH_setint (lua_State *L, Table *t, lua_Integer key) {
- + const TValue *p = luaH_getint(t, key);
- if (p != luaO_nilobject)
- return cast(TValue *, p);
- else {
- TValue k;
- - setnvalue(&k, cast_num(key));
- + setivalue(&k, key);
- return newkey(L, t, &k);
- }
- }
- @@ -533,20 +553,21 @@ static int unbound_search (Table *t, uns
- unsigned int i = j; /* i is zero or a present index */
- j++;
- /* find `i' and `j' such that i is present and j is not */
- - while (!ttisnil(luaH_getnum(t, j))) {
- + while (!ttisnil(luaH_getint(t, j))) {
- i = j;
- j *= 2;
- if (j > cast(unsigned int, MAX_INT)) { /* overflow? */
- /* table was built with bad purposes: resort to linear search */
- - i = 1;
- - while (!ttisnil(luaH_getnum(t, i))) i++;
- - return i - 1;
- + for( i = 1; i<MAX_INT+1; i++ ) {
- + if (ttisnil(luaH_getint(t, i))) break;
- + }
- + return i - 1; /* up to MAX_INT */
- }
- }
- /* now do a binary search between them */
- while (j - i > 1) {
- unsigned int m = (i+j)/2;
- - if (ttisnil(luaH_getnum(t, m))) j = m;
- + if (ttisnil(luaH_getint(t, m))) j = m;
- else i = m;
- }
- return i;
- --- a/src/ltable.h
- +++ b/src/ltable.h
- @@ -18,8 +18,8 @@
- #define key2tval(n) (&(n)->i_key.tvk)
-
-
- -LUAI_FUNC const TValue *luaH_getnum (Table *t, int key);
- -LUAI_FUNC TValue *luaH_setnum (lua_State *L, Table *t, int key);
- +LUAI_FUNC const TValue *luaH_getint (Table *t, lua_Integer key);
- +LUAI_FUNC TValue *luaH_setint (lua_State *L, Table *t, lua_Integer key);
- LUAI_FUNC const TValue *luaH_getstr (Table *t, TString *key);
- LUAI_FUNC TValue *luaH_setstr (lua_State *L, Table *t, TString *key);
- LUAI_FUNC const TValue *luaH_get (Table *t, const TValue *key);
- --- a/src/ltm.c
- +++ b/src/ltm.c
- @@ -19,7 +19,6 @@
- #include "ltm.h"
-
-
- -
- const char *const luaT_typenames[] = {
- "nil", "boolean", "userdata", "number",
- "string", "table", "function", "userdata", "thread",
- @@ -67,6 +66,9 @@ const TValue *luaT_gettmbyobj (lua_State
- case LUA_TUSERDATA:
- mt = uvalue(o)->metatable;
- break;
- + case LUA_TINT:
- + mt = G(L)->mt[LUA_TNUMBER];
- + break;
- default:
- mt = G(L)->mt[ttype(o)];
- }
- --- a/src/lua.c
- +++ b/src/lua.c
- @@ -16,7 +16,7 @@
-
- #include "lauxlib.h"
- #include "lualib.h"
- -
- +#include "llimits.h"
-
-
- static lua_State *globalL = NULL;
- @@ -382,6 +382,15 @@ int main (int argc, char **argv) {
- l_message(argv[0], "cannot create state: not enough memory");
- return EXIT_FAILURE;
- }
- + /* Checking 'sizeof(lua_Integer)' cannot be made in preprocessor on all compilers.
- + */
- +#ifdef LNUM_INT16
- + lua_assert( sizeof(lua_Integer) == 2 );
- +#elif defined(LNUM_INT32)
- + lua_assert( sizeof(lua_Integer) == 4 );
- +#elif defined(LNUM_INT64)
- + lua_assert( sizeof(lua_Integer) == 8 );
- +#endif
- s.argc = argc;
- s.argv = argv;
- status = lua_cpcall(L, &pmain, &s);
- --- a/src/lua.h
- +++ b/src/lua.h
- @@ -19,7 +19,7 @@
- #define LUA_VERSION "Lua 5.1"
- #define LUA_RELEASE "Lua 5.1.5"
- #define LUA_VERSION_NUM 501
- -#define LUA_COPYRIGHT "Copyright (C) 1994-2012 Lua.org, PUC-Rio"
- +#define LUA_COPYRIGHT "Copyright (C) 1994-2012 Lua.org, PUC-Rio" " (" LUA_LNUM ")"
- #define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo & W. Celes"
-
-
- @@ -71,6 +71,16 @@ typedef void * (*lua_Alloc) (void *ud, v
- */
- #define LUA_TNONE (-1)
-
- +/* LUA_TINT is an internal type, not visible to applications. There are three
- + * potential values where it can be tweaked to (code autoadjusts to these):
- + *
- + * -2: not 'usual' type value; good since 'LUA_TINT' is not part of the API
- + * LUA_TNUMBER+1: shifts other type values upwards, breaking binary compatibility
- + * not acceptable for 5.1, maybe 5.2 onwards?
- + * 9: greater than existing (5.1) type values.
- +*/
- +#define LUA_TINT (-2)
- +
- #define LUA_TNIL 0
- #define LUA_TBOOLEAN 1
- #define LUA_TLIGHTUSERDATA 2
- @@ -139,6 +149,8 @@ LUA_API int (lua_isuserdata)
- LUA_API int (lua_type) (lua_State *L, int idx);
- LUA_API const char *(lua_typename) (lua_State *L, int tp);
-
- +LUA_API int (lua_isinteger) (lua_State *L, int idx);
- +
- LUA_API int (lua_equal) (lua_State *L, int idx1, int idx2);
- LUA_API int (lua_rawequal) (lua_State *L, int idx1, int idx2);
- LUA_API int (lua_lessthan) (lua_State *L, int idx1, int idx2);
- @@ -244,6 +256,19 @@ LUA_API lua_Alloc (lua_getallocf) (lua_S
- LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud);
-
-
- +/*
- +* It is unnecessary to break Lua C API 'lua_tonumber()' compatibility, just
- +* because the Lua number type is complex. Most C modules would use scalars
- +* only. We'll introduce new 'lua_tocomplex' and 'lua_pushcomplex' for when
- +* the module really wants to use them.
- +*/
- +#ifdef LNUM_COMPLEX
- + #include <complex.h>
- + typedef LUA_NUMBER complex lua_Complex;
- + LUA_API lua_Complex (lua_tocomplex) (lua_State *L, int idx);
- + LUA_API void (lua_pushcomplex) (lua_State *L, lua_Complex v);
- +#endif
- +
-
- /*
- ** ===============================================================
- @@ -268,7 +293,12 @@ LUA_API void lua_setallocf (lua_State *L
- #define lua_isboolean(L,n) (lua_type(L, (n)) == LUA_TBOOLEAN)
- #define lua_isthread(L,n) (lua_type(L, (n)) == LUA_TTHREAD)
- #define lua_isnone(L,n) (lua_type(L, (n)) == LUA_TNONE)
- -#define lua_isnoneornil(L, n) (lua_type(L, (n)) <= 0)
- +
- +#if LUA_TINT < 0
- +# define lua_isnoneornil(L, n) ( (lua_type(L,(n)) <= 0) && (lua_type(L,(n)) != LUA_TINT) )
- +#else
- +# define lua_isnoneornil(L, n) (lua_type(L, (n)) <= 0)
- +#endif
-
- #define lua_pushliteral(L, s) \
- lua_pushlstring(L, "" s, (sizeof(s)/sizeof(char))-1)
- @@ -386,3 +416,4 @@ struct lua_Debug {
-
-
- #endif
- +
- --- a/src/luaconf.h
- +++ b/src/luaconf.h
- @@ -10,7 +10,9 @@
-
- #include <limits.h>
- #include <stddef.h>
- -
- +#ifdef lua_assert
- +# include <assert.h>
- +#endif
-
- /*
- ** ==================================================================
- @@ -136,14 +138,38 @@
-
-
- /*
- -@@ LUA_INTEGER is the integral type used by lua_pushinteger/lua_tointeger.
- -** CHANGE that if ptrdiff_t is not adequate on your machine. (On most
- -** machines, ptrdiff_t gives a good choice between int or long.)
- +@@ LUAI_BITSINT defines the number of bits in an int.
- +** CHANGE here if Lua cannot automatically detect the number of bits of
- +** your machine. Probably you do not need to change this.
- */
- -#define LUA_INTEGER ptrdiff_t
- +/* avoid overflows in comparison */
- +#if INT_MAX-20 < 32760
- +#define LUAI_BITSINT 16
- +#elif INT_MAX > 2147483640L
- +/* int has at least 32 bits */
- +#define LUAI_BITSINT 32
- +#else
- +#error "you must define LUA_BITSINT with number of bits in an integer"
- +#endif
-
-
- /*
- +@@ LNUM_DOUBLE | LNUM_FLOAT | LNUM_LDOUBLE: Generic Lua number mode
- +@@ LNUM_INT32 | LNUM_INT64: Integer type
- +@@ LNUM_COMPLEX: Define for using 'a+bi' numbers
- +@@
- +@@ You can combine LNUM_xxx but only one of each group. I.e. '-DLNUM_FLOAT
- +@@ -DLNUM_INT32 -DLNUM_COMPLEX' gives float range complex numbers, with
- +@@ 32-bit scalar integer range optimized.
- +**
- +** These are kept in a separate configuration file mainly for ease of patching
- +** (can be changed if integerated to Lua proper).
- +*/
- +/*#define LNUM_DOUBLE*/
- +/*#define LNUM_INT32*/
- +#include "lnum_config.h"
- +
- +/*
- @@ LUA_API is a mark for all core API functions.
- @@ LUALIB_API is a mark for all standard library functions.
- ** CHANGE them if you need to define those functions in some special way.
- @@ -383,22 +409,6 @@
-
-
- /*
- -@@ LUAI_BITSINT defines the number of bits in an int.
- -** CHANGE here if Lua cannot automatically detect the number of bits of
- -** your machine. Probably you do not need to change this.
- -*/
- -/* avoid overflows in comparison */
- -#if INT_MAX-20 < 32760
- -#define LUAI_BITSINT 16
- -#elif INT_MAX > 2147483640L
- -/* int has at least 32 bits */
- -#define LUAI_BITSINT 32
- -#else
- -#error "you must define LUA_BITSINT with number of bits in an integer"
- -#endif
- -
- -
- -/*
- @@ LUAI_UINT32 is an unsigned integer with at least 32 bits.
- @@ LUAI_INT32 is an signed integer with at least 32 bits.
- @@ LUAI_UMEM is an unsigned integer big enough to count the total
- @@ -425,6 +435,15 @@
- #define LUAI_MEM long
- #endif
-
- +/*
- +@@ LUAI_BOOL carries 0 and nonzero (normally 1). It may be defined as 'char'
- +** (to save memory), 'int' (for speed), 'bool' (for C++) or '_Bool' (C99)
- +*/
- +#ifdef __cplusplus
- +# define LUAI_BOOL bool
- +#else
- +# define LUAI_BOOL int
- +#endif
-
- /*
- @@ LUAI_MAXCALLS limits the number of nested calls.
- @@ -490,101 +509,6 @@
- /* }================================================================== */
-
-
- -
- -
- -/*
- -** {==================================================================
- -@@ LUA_NUMBER is the type of numbers in Lua.
- -** CHANGE the following definitions only if you want to build Lua
- -** with a number type different from double. You may also need to
- -** change lua_number2int & lua_number2integer.
- -** ===================================================================
- -*/
- -
- -#define LUA_NUMBER_DOUBLE
- -#define LUA_NUMBER double
- -
- -/*
- -@@ LUAI_UACNUMBER is the result of an 'usual argument conversion'
- -@* over a number.
- -*/
- -#define LUAI_UACNUMBER double
- -
- -
- -/*
- -@@ LUA_NUMBER_SCAN is the format for reading numbers.
- -@@ LUA_NUMBER_FMT is the format for writing numbers.
- -@@ lua_number2str converts a number to a string.
- -@@ LUAI_MAXNUMBER2STR is maximum size of previous conversion.
- -@@ lua_str2number converts a string to a number.
- -*/
- -#define LUA_NUMBER_SCAN "%lf"
- -#define LUA_NUMBER_FMT "%.14g"
- -#define lua_number2str(s,n) sprintf((s), LUA_NUMBER_FMT, (n))
- -#define LUAI_MAXNUMBER2STR 32 /* 16 digits, sign, point, and \0 */
- -#define lua_str2number(s,p) strtod((s), (p))
- -
- -
- -/*
- -@@ The luai_num* macros define the primitive operations over numbers.
- -*/
- -#if defined(LUA_CORE)
- -#include <math.h>
- -#define luai_numadd(a,b) ((a)+(b))
- -#define luai_numsub(a,b) ((a)-(b))
- -#define luai_nummul(a,b) ((a)*(b))
- -#define luai_numdiv(a,b) ((a)/(b))
- -#define luai_nummod(a,b) ((a) - floor((a)/(b))*(b))
- -#define luai_numpow(a,b) (pow(a,b))
- -#define luai_numunm(a) (-(a))
- -#define luai_numeq(a,b) ((a)==(b))
- -#define luai_numlt(a,b) ((a)<(b))
- -#define luai_numle(a,b) ((a)<=(b))
- -#define luai_numisnan(a) (!luai_numeq((a), (a)))
- -#endif
- -
- -
- -/*
- -@@ lua_number2int is a macro to convert lua_Number to int.
- -@@ lua_number2integer is a macro to convert lua_Number to lua_Integer.
- -** 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.
- -*/
- -
- -/* On a Pentium, resort to a trick */
- -#if defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) && !defined(__SSE2__) && \
- - (defined(__i386) || defined (_M_IX86) || defined(__i386__))
- -
- -/* On a Microsoft compiler, use assembler */
- -#if defined(_MSC_VER)
- -
- -#define lua_number2int(i,d) __asm fld d __asm fistp i
- -#define lua_number2integer(i,n) lua_number2int(i, n)
- -
- -/* the next trick should work on any Pentium, but sometimes clashes
- - with a DirectX idiosyncrasy */
- -#else
- -
- -union luai_Cast { double l_d; long l_l; };
- -#define lua_number2int(i,d) \
- - { volatile union luai_Cast u; u.l_d = (d) + 6755399441055744.0; (i) = u.l_l; }
- -#define lua_number2integer(i,n) lua_number2int(i, n)
- -
- -#endif
- -
- -
- -/* this option always works, but may be slow */
- -#else
- -#define lua_number2int(i,d) ((i)=(int)(d))
- -#define lua_number2integer(i,d) ((i)=(lua_Integer)(d))
- -
- -#endif
- -
- -/* }================================================================== */
- -
- -
- /*
- @@ LUAI_USER_ALIGNMENT_T is a type that requires maximum alignment.
- ** CHANGE it if your system requires alignments larger than double. (For
- @@ -728,28 +652,6 @@ union luai_Cast { double l_d; long l_l;
- #define luai_userstateyield(L,n) ((void)L)
-
-
- -/*
- -@@ LUA_INTFRMLEN is the length modifier for integer conversions
- -@* in 'string.format'.
- -@@ LUA_INTFRM_T is the integer type correspoding to the previous length
- -@* modifier.
- -** CHANGE them if your system supports long long or does not support long.
- -*/
- -
- -#if defined(LUA_USELONGLONG)
- -
- -#define LUA_INTFRMLEN "ll"
- -#define LUA_INTFRM_T long long
- -
- -#else
- -
- -#define LUA_INTFRMLEN "l"
- -#define LUA_INTFRM_T long
- -
- -#endif
- -
- -
- -
- /* =================================================================== */
-
- /*
- --- a/src/lundump.c
- +++ b/src/lundump.c
- @@ -73,6 +73,13 @@ static lua_Number LoadNumber(LoadState*
- return x;
- }
-
- +static lua_Integer LoadInteger(LoadState* S)
- +{
- + lua_Integer x;
- + LoadVar(S,x);
- + return x;
- +}
- +
- static TString* LoadString(LoadState* S)
- {
- size_t size;
- @@ -119,6 +126,9 @@ static void LoadConstants(LoadState* S,
- case LUA_TNUMBER:
- setnvalue(o,LoadNumber(S));
- break;
- + case LUA_TINT: /* Integer type saved in bytecode (see lcode.c) */
- + setivalue(o,LoadInteger(S));
- + break;
- case LUA_TSTRING:
- setsvalue2n(S->L,o,LoadString(S));
- break;
- @@ -223,5 +233,22 @@ void luaU_header (char* h)
- *h++=(char)sizeof(size_t);
- *h++=(char)sizeof(Instruction);
- *h++=(char)sizeof(lua_Number);
- - *h++=(char)(((lua_Number)0.5)==0); /* is lua_Number integral? */
- +
- + /*
- + * Last byte of header (0/1 in unpatched Lua 5.1.3):
- + *
- + * 0: lua_Number is float or double, lua_Integer not used. (nonpatched only)
- + * 1: lua_Number is integer (nonpatched only)
- + *
- + * +2: LNUM_INT16: sizeof(lua_Integer)
- + * +4: LNUM_INT32: sizeof(lua_Integer)
- + * +8: LNUM_INT64: sizeof(lua_Integer)
- + *
- + * +0x80: LNUM_COMPLEX
- + */
- + *h++ = (char)(sizeof(lua_Integer)
- +#ifdef LNUM_COMPLEX
- + | 0x80
- +#endif
- + );
- }
- --- a/src/lvm.c
- +++ b/src/lvm.c
- @@ -25,22 +25,35 @@
- #include "ltable.h"
- #include "ltm.h"
- #include "lvm.h"
- -
- -
- +#include "llex.h"
- +#include "lnum.h"
-
- /* limit for table tag-method chains (to avoid loops) */
- #define MAXTAGLOOP 100
-
-
- -const TValue *luaV_tonumber (const TValue *obj, TValue *n) {
- - lua_Number num;
- +/*
- + * If 'obj' is a string, it is tried to be interpreted as a number.
- + */
- +const TValue *luaV_tonumber ( const TValue *obj, TValue *n) {
- + lua_Number d;
- + lua_Integer i;
- +
- if (ttisnumber(obj)) return obj;
- - if (ttisstring(obj) && luaO_str2d(svalue(obj), &num)) {
- - setnvalue(n, num);
- - return n;
- - }
- - else
- - return NULL;
- +
- + if (ttisstring(obj)) {
- + switch( luaO_str2d( svalue(obj), &d, &i ) ) {
- + case TK_INT:
- + setivalue(n,i); return n;
- + case TK_NUMBER:
- + setnvalue(n,d); return n;
- +#ifdef LNUM_COMPLEX
- + case TK_NUMBER2: /* "N.NNNi", != 0 */
- + setnvalue_complex_fast(n, d*I); return n;
- +#endif
- + }
- + }
- + return NULL;
- }
-
-
- @@ -49,8 +62,7 @@ int luaV_tostring (lua_State *L, StkId o
- return 0;
- else {
- char s[LUAI_MAXNUMBER2STR];
- - lua_Number n = nvalue(obj);
- - lua_number2str(s, n);
- + luaO_num2buf(s,obj);
- setsvalue2s(L, obj, luaS_new(L, s));
- return 1;
- }
- @@ -222,59 +234,127 @@ static int l_strcmp (const TString *ls,
- }
-
-
- +#ifdef LNUM_COMPLEX
- +void error_complex( lua_State *L, const TValue *l, const TValue *r )
- +{
- + char buf1[ LUAI_MAXNUMBER2STR ];
- + char buf2[ LUAI_MAXNUMBER2STR ];
- + luaO_num2buf( buf1, l );
- + luaO_num2buf( buf2, r );
- + luaG_runerror( L, "unable to compare: %s with %s", buf1, buf2 );
- + /* no return */
- +}
- +#endif
- +
- +
- int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) {
- int res;
- - if (ttype(l) != ttype(r))
- + int tl,tr;
- + lua_Integer tmp;
- +
- + if (!ttype_ext_same(l,r))
- return luaG_ordererror(L, l, r);
- - else if (ttisnumber(l))
- - return luai_numlt(nvalue(l), nvalue(r));
- - else if (ttisstring(l))
- - return l_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0;
- - else if ((res = call_orderTM(L, l, r, TM_LT)) != -1)
- +#ifdef LNUM_COMPLEX
- + if ( (nvalue_img(l)!=0) || (nvalue_img(r)!=0) )
- + error_complex( L, l, r );
- +#endif
- + tl= ttype(l); tr= ttype(r);
- + if (tl==tr) { /* clear arithmetics */
- + switch(tl) {
- + case LUA_TINT: return ivalue(l) < ivalue(r);
- + case LUA_TNUMBER: return luai_numlt(nvalue_fast(l), nvalue_fast(r));
- + case LUA_TSTRING: return l_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0;
- + }
- + } else if (tl==LUA_TINT) { /* l:int, r:num */
- + /* Avoid accuracy losing casts: if 'r' is integer by value, do comparisons
- + * in integer realm. Only otherwise cast 'l' to FP (which might change its
- + * value).
- + */
- + if (tt_integer_valued(r,&tmp))
- + return ivalue(l) < tmp;
- + else
- + return luai_numlt( cast_num(ivalue(l)), nvalue_fast(r) );
- +
- + } else if (tl==LUA_TNUMBER) { /* l:num, r:int */
- + if (tt_integer_valued(l,&tmp))
- + return tmp < ivalue(r);
- + else
- + return luai_numlt( nvalue_fast(l), cast_num(ivalue(r)) );
- +
- + } else if ((res = call_orderTM(L, l, r, TM_LT)) != -1)
- return res;
- +
- return luaG_ordererror(L, l, r);
- }
-
-
- static int lessequal (lua_State *L, const TValue *l, const TValue *r) {
- int res;
- - if (ttype(l) != ttype(r))
- + int tl, tr;
- + lua_Integer tmp;
- +
- + if (!ttype_ext_same(l,r))
- return luaG_ordererror(L, l, r);
- - else if (ttisnumber(l))
- - return luai_numle(nvalue(l), nvalue(r));
- - else if (ttisstring(l))
- - return l_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0;
- - else if ((res = call_orderTM(L, l, r, TM_LE)) != -1) /* first try `le' */
- +#ifdef LNUM_COMPLEX
- + if ( (nvalue_img(l)!=0) || (nvalue_img(r)!=0) )
- + error_complex( L, l, r );
- +#endif
- + tl= ttype(l); tr= ttype(r);
- + if (tl==tr) { /* clear arithmetics */
- + switch(tl) {
- + case LUA_TINT: return ivalue(l) <= ivalue(r);
- + case LUA_TNUMBER: return luai_numle(nvalue_fast(l), nvalue_fast(r));
- + case LUA_TSTRING: return l_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0;
- + }
- + }
- + if (tl==LUA_TINT) { /* l:int, r:num */
- + if (tt_integer_valued(r,&tmp))
- + return ivalue(l) <= tmp;
- + else
- + return luai_numle( cast_num(ivalue(l)), nvalue_fast(r) );
- +
- + } else if (tl==LUA_TNUMBER) { /* l:num, r:int */
- + if (tt_integer_valued(l,&tmp))
- + return tmp <= ivalue(r);
- + else
- + return luai_numle( nvalue_fast(l), cast_num(ivalue(r)) );
- +
- + } else if ((res = call_orderTM(L, l, r, TM_LE)) != -1) /* first try `le' */
- return res;
- else if ((res = call_orderTM(L, r, l, TM_LT)) != -1) /* else try `lt' */
- return !res;
- +
- return luaG_ordererror(L, l, r);
- }
-
-
- -int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2) {
- +/* Note: 'luaV_equalval()' and 'luaO_rawequalObj()' have largely overlapping
- + * implementation. LUA_TNIL..LUA_TLIGHTUSERDATA cases could be handled
- + * simply by the 'default' case here.
- + */
- +int luaV_equalval (lua_State *L, const TValue *l, const TValue *r) {
- const TValue *tm;
- - lua_assert(ttype(t1) == ttype(t2));
- - switch (ttype(t1)) {
- + lua_assert(ttype_ext_same(l,r));
- + switch (ttype(l)) {
- case LUA_TNIL: return 1;
- - case LUA_TNUMBER: return luai_numeq(nvalue(t1), nvalue(t2));
- - case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2); /* true must be 1 !! */
- - case LUA_TLIGHTUSERDATA: return pvalue(t1) == pvalue(t2);
- + case LUA_TINT:
- + case LUA_TNUMBER: return luaO_rawequalObj(l,r);
- + case LUA_TBOOLEAN: return bvalue(l) == bvalue(r); /* true must be 1 !! */
- + case LUA_TLIGHTUSERDATA: return pvalue(l) == pvalue(r);
- case LUA_TUSERDATA: {
- - if (uvalue(t1) == uvalue(t2)) return 1;
- - tm = get_compTM(L, uvalue(t1)->metatable, uvalue(t2)->metatable,
- - TM_EQ);
- + if (uvalue(l) == uvalue(r)) return 1;
- + tm = get_compTM(L, uvalue(l)->metatable, uvalue(r)->metatable, TM_EQ);
- break; /* will try TM */
- }
- case LUA_TTABLE: {
- - if (hvalue(t1) == hvalue(t2)) return 1;
- - tm = get_compTM(L, hvalue(t1)->metatable, hvalue(t2)->metatable, TM_EQ);
- + if (hvalue(l) == hvalue(r)) return 1;
- + tm = get_compTM(L, hvalue(l)->metatable, hvalue(r)->metatable, TM_EQ);
- break; /* will try TM */
- }
- - default: return gcvalue(t1) == gcvalue(t2);
- + default: return gcvalue(l) == gcvalue(r);
- }
- if (tm == NULL) return 0; /* no TM? */
- - callTMres(L, L->top, tm, t1, t2); /* call TM */
- + callTMres(L, L->top, tm, l, r); /* call TM */
- return !l_isfalse(L->top);
- }
-
- @@ -314,30 +394,6 @@ void luaV_concat (lua_State *L, int tota
- }
-
-
- -static void Arith (lua_State *L, StkId ra, const TValue *rb,
- - const TValue *rc, TMS op) {
- - TValue tempb, tempc;
- - const TValue *b, *c;
- - if ((b = luaV_tonumber(rb, &tempb)) != NULL &&
- - (c = luaV_tonumber(rc, &tempc)) != NULL) {
- - lua_Number nb = nvalue(b), nc = nvalue(c);
- - switch (op) {
- - case TM_ADD: setnvalue(ra, luai_numadd(nb, nc)); break;
- - case TM_SUB: setnvalue(ra, luai_numsub(nb, nc)); break;
- - case TM_MUL: setnvalue(ra, luai_nummul(nb, nc)); break;
- - case TM_DIV: setnvalue(ra, luai_numdiv(nb, nc)); break;
- - case TM_MOD: setnvalue(ra, luai_nummod(nb, nc)); break;
- - case TM_POW: setnvalue(ra, luai_numpow(nb, nc)); break;
- - case TM_UNM: setnvalue(ra, luai_numunm(nb)); break;
- - default: lua_assert(0); break;
- - }
- - }
- - else if (!call_binTM(L, rb, rc, ra, op))
- - luaG_aritherror(L, rb, rc);
- -}
- -
- -
- -
- /*
- ** some macros for common tasks in `luaV_execute'
- */
- @@ -361,17 +417,154 @@ static void Arith (lua_State *L, StkId r
- #define Protect(x) { L->savedpc = pc; {x;}; base = L->base; }
-
-
- -#define arith_op(op,tm) { \
- - TValue *rb = RKB(i); \
- - TValue *rc = RKC(i); \
- - if (ttisnumber(rb) && ttisnumber(rc)) { \
- - lua_Number nb = nvalue(rb), nc = nvalue(rc); \
- - setnvalue(ra, op(nb, nc)); \
- - } \
- - else \
- - Protect(Arith(L, ra, rb, rc, tm)); \
- +/* Note: if called for unary operations, 'rc'=='rb'.
- + */
- +static void Arith (lua_State *L, StkId ra, const TValue *rb,
- + const TValue *rc, TMS op) {
- + TValue tempb, tempc;
- + const TValue *b, *c;
- + lua_Number nb,nc;
- +
- + if ((b = luaV_tonumber(rb, &tempb)) != NULL &&
- + (c = luaV_tonumber(rc, &tempc)) != NULL) {
- +
- + /* Keep integer arithmetics in the integer realm, if possible.
- + */
- + if (ttisint(b) && ttisint(c)) {
- + lua_Integer ib = ivalue(b), ic = ivalue(c);
- + lua_Integer *ri = &ra->value.i;
- + ra->tt= LUA_TINT; /* part of 'setivalue(ra)' */
- + switch (op) {
- + case TM_ADD: if (try_addint( ri, ib, ic)) return; break;
- + case TM_SUB: if (try_subint( ri, ib, ic)) return; break;
- + case TM_MUL: if (try_mulint( ri, ib, ic)) return; break;
- + case TM_DIV: if (try_divint( ri, ib, ic)) return; break;
- + case TM_MOD: if (try_modint( ri, ib, ic)) return; break;
- + case TM_POW: if (try_powint( ri, ib, ic)) return; break;
- + case TM_UNM: if (try_unmint( ri, ib)) return; break;
- + default: lua_assert(0);
- + }
- + }
- + /* Fallback to floating point, when leaving range. */
- +
- +#ifdef LNUM_COMPLEX
- + if ((nvalue_img(b)!=0) || (nvalue_img(c)!=0)) {
- + lua_Complex r;
- + if (op==TM_UNM) {
- + r= -nvalue_complex_fast(b); /* never an integer (or scalar) */
- + setnvalue_complex_fast( ra, r );
- + } else {
- + lua_Complex bb= nvalue_complex(b), cc= nvalue_complex(c);
- + switch (op) {
- + case TM_ADD: r= bb + cc; break;
- + case TM_SUB: r= bb - cc; break;
- + case TM_MUL: r= bb * cc; break;
- + case TM_DIV: r= bb / cc; break;
- + case TM_MOD:
- + luaG_runerror(L, "attempt to use %% on complex numbers"); /* no return */
- + case TM_POW: r= luai_vectpow( bb, cc ); break;
- + default: lua_assert(0); r=0;
- + }
- + setnvalue_complex( ra, r );
- }
- + return;
- + }
- +#endif
- + nb = nvalue(b); nc = nvalue(c);
- + switch (op) {
- + case TM_ADD: setnvalue(ra, luai_numadd(nb, nc)); return;
- + case TM_SUB: setnvalue(ra, luai_numsub(nb, nc)); return;
- + case TM_MUL: setnvalue(ra, luai_nummul(nb, nc)); return;
- + case TM_DIV: setnvalue(ra, luai_numdiv(nb, nc)); return;
- + case TM_MOD: setnvalue(ra, luai_nummod(nb, nc)); return;
- + case TM_POW: setnvalue(ra, luai_numpow(nb, nc)); return;
- + case TM_UNM: setnvalue(ra, luai_numunm(nb)); return;
- + default: lua_assert(0);
- + }
- + }
- +
- + /* Either operand not a number */
- + if (!call_binTM(L, rb, rc, ra, op))
- + luaG_aritherror(L, rb, rc);
- +}
-
- +/* Helper macro to sort arithmetic operations into four categories:
- + * TK_INT: integer - integer operands
- + * TK_NUMBER: number - number (non complex, either may be integer)
- + * TK_NUMBER2: complex numbers (at least the other)
- + * 0: non-numeric (at least the other)
- +*/
- +#ifdef LNUM_COMPLEX
- +static inline int arith_mode( const TValue *rb, const TValue *rc ) {
- + if (ttisint(rb) && ttisint(rc)) return TK_INT;
- + if (ttiscomplex(rb) || ttiscomplex(rc)) return TK_NUMBER2;
- + if (ttisnumber(rb) && ttisnumber(rc)) return TK_NUMBER;
- + return 0;
- +}
- +#else
- +# define arith_mode(rb,rc) \
- + ( (ttisint(rb) && ttisint(rc)) ? TK_INT : \
- + (ttisnumber(rb) && ttisnumber(rc)) ? TK_NUMBER : 0 )
- +#endif
- +
- +/* arith_op macro for two operators:
- + * automatically chooses, which function (number, integer, complex) to use
- + */
- +#define ARITH_OP2_START( op_num, op_int ) \
- + int failed= 0; \
- + switch( arith_mode(rb,rc) ) { \
- + case TK_INT: \
- + if (op_int ( &(ra)->value.i, ivalue(rb), ivalue(rc) )) \
- + { ra->tt= LUA_TINT; break; } /* else flow through */ \
- + case TK_NUMBER: \
- + setnvalue(ra, op_num ( nvalue(rb), nvalue(rc) )); break;
- +
- +#define ARITH_OP2_END \
- + default: \
- + failed= 1; break; \
- + } if (!failed) continue;
- +
- +#define arith_op_continue_scalar( op_num, op_int ) \
- + ARITH_OP2_START( op_num, op_int ) \
- + ARITH_OP2_END
- +
- +#ifdef LNUM_COMPLEX
- +# define arith_op_continue( op_num, op_int, op_complex ) \
- + ARITH_OP2_START( op_num, op_int ) \
- + case TK_NUMBER2: \
- + setnvalue_complex( ra, op_complex ( nvalue_complex(rb), nvalue_complex(rc) ) ); break; \
- + ARITH_OP2_END
- +#else
- +# define arith_op_continue(op_num,op_int,_) arith_op_continue_scalar(op_num,op_int)
- +#endif
- +
- +/* arith_op macro for one operator:
- + */
- +#define ARITH_OP1_START( op_num, op_int ) \
- + int failed= 0; \
- + switch( arith_mode(rb,rb) ) { \
- + case TK_INT: \
- + if (op_int ( &(ra)->value.i, ivalue(rb) )) \
- + { ra->tt= LUA_TINT; break; } /* else flow through */ \
- + case TK_NUMBER: \
- + setnvalue(ra, op_num (nvalue(rb))); break; \
- +
- +#define ARITH_OP1_END \
- + default: \
- + failed= 1; break; \
- + } if (!failed) continue;
- +
- +#ifdef LNUM_COMPLEX
- +# define arith_op1_continue( op_num, op_int, op_complex ) \
- + ARITH_OP1_START( op_num, op_int ) \
- + case TK_NUMBER2: \
- + setnvalue_complex( ra, op_complex ( nvalue_complex_fast(rb) )); break; \
- + ARITH_OP1_END
- +#else
- +# define arith_op1_continue( op_num, op_int, _ ) \
- + ARITH_OP1_START( op_num, op_int ) \
- + ARITH_OP1_END
- +#endif
-
-
- void luaV_execute (lua_State *L, int nexeccalls) {
- @@ -472,38 +665,45 @@ void luaV_execute (lua_State *L, int nex
- continue;
- }
- case OP_ADD: {
- - arith_op(luai_numadd, TM_ADD);
- + TValue *rb = RKB(i), *rc= RKC(i);
- + arith_op_continue( luai_numadd, try_addint, luai_vectadd );
- + Protect(Arith(L, ra, rb, rc, TM_ADD)); \
- continue;
- }
- case OP_SUB: {
- - arith_op(luai_numsub, TM_SUB);
- + TValue *rb = RKB(i), *rc= RKC(i);
- + arith_op_continue( luai_numsub, try_subint, luai_vectsub );
- + Protect(Arith(L, ra, rb, rc, TM_SUB));
- continue;
- }
- case OP_MUL: {
- - arith_op(luai_nummul, TM_MUL);
- + TValue *rb = RKB(i), *rc= RKC(i);
- + arith_op_continue(luai_nummul, try_mulint, luai_vectmul);
- + Protect(Arith(L, ra, rb, rc, TM_MUL));
- continue;
- }
- case OP_DIV: {
- - arith_op(luai_numdiv, TM_DIV);
- + TValue *rb = RKB(i), *rc= RKC(i);
- + arith_op_continue(luai_numdiv, try_divint, luai_vectdiv);
- + Protect(Arith(L, ra, rb, rc, TM_DIV));
- continue;
- }
- case OP_MOD: {
- - arith_op(luai_nummod, TM_MOD);
- + TValue *rb = RKB(i), *rc= RKC(i);
- + arith_op_continue_scalar(luai_nummod, try_modint); /* scalars only */
- + Protect(Arith(L, ra, rb, rc, TM_MOD));
- continue;
- }
- case OP_POW: {
- - arith_op(luai_numpow, TM_POW);
- + TValue *rb = RKB(i), *rc= RKC(i);
- + arith_op_continue(luai_numpow, try_powint, luai_vectpow);
- + Protect(Arith(L, ra, rb, rc, TM_POW));
- continue;
- }
- case OP_UNM: {
- TValue *rb = RB(i);
- - if (ttisnumber(rb)) {
- - lua_Number nb = nvalue(rb);
- - setnvalue(ra, luai_numunm(nb));
- - }
- - else {
- - Protect(Arith(L, ra, rb, rb, TM_UNM));
- - }
- + arith_op1_continue(luai_numunm, try_unmint, luai_vectunm);
- + Protect(Arith(L, ra, rb, rb, TM_UNM));
- continue;
- }
- case OP_NOT: {
- @@ -515,11 +715,11 @@ void luaV_execute (lua_State *L, int nex
- const TValue *rb = RB(i);
- switch (ttype(rb)) {
- case LUA_TTABLE: {
- - setnvalue(ra, cast_num(luaH_getn(hvalue(rb))));
- + setivalue(ra, luaH_getn(hvalue(rb)));
- break;
- }
- case LUA_TSTRING: {
- - setnvalue(ra, cast_num(tsvalue(rb)->len));
- + setivalue(ra, tsvalue(rb)->len);
- break;
- }
- default: { /* try metamethod */
- @@ -652,14 +852,30 @@ void luaV_execute (lua_State *L, int nex
- }
- }
- case OP_FORLOOP: {
- - lua_Number step = nvalue(ra+2);
- - lua_Number idx = luai_numadd(nvalue(ra), step); /* increment index */
- - lua_Number limit = nvalue(ra+1);
- - if (luai_numlt(0, step) ? luai_numle(idx, limit)
- - : luai_numle(limit, idx)) {
- - dojump(L, pc, GETARG_sBx(i)); /* jump back */
- - setnvalue(ra, idx); /* update internal index... */
- - setnvalue(ra+3, idx); /* ...and external index */
- + /* If start,step and limit are all integers, we don't need to check
- + * against overflow in the looping.
- + */
- + if (ttisint(ra) && ttisint(ra+1) && ttisint(ra+2)) {
- + lua_Integer step = ivalue(ra+2);
- + lua_Integer idx = ivalue(ra) + step; /* increment index */
- + lua_Integer limit = ivalue(ra+1);
- + if (step > 0 ? (idx <= limit) : (limit <= idx)) {
- + dojump(L, pc, GETARG_sBx(i)); /* jump back */
- + setivalue(ra, idx); /* update internal index... */
- + setivalue(ra+3, idx); /* ...and external index */
- + }
- + } else {
- + /* non-integer looping (don't use 'nvalue_fast', some may be integer!)
- + */
- + lua_Number step = nvalue(ra+2);
- + lua_Number idx = luai_numadd(nvalue(ra), step); /* increment index */
- + lua_Number limit = nvalue(ra+1);
- + if (luai_numlt(0, step) ? luai_numle(idx, limit)
- + : luai_numle(limit, idx)) {
- + dojump(L, pc, GETARG_sBx(i)); /* jump back */
- + setnvalue(ra, idx); /* update internal index... */
- + setnvalue(ra+3, idx); /* ...and external index */
- + }
- }
- continue;
- }
- @@ -668,13 +884,21 @@ void luaV_execute (lua_State *L, int nex
- const TValue *plimit = ra+1;
- const TValue *pstep = ra+2;
- L->savedpc = pc; /* next steps may throw errors */
- + /* Using same location for tonumber's both arguments, effectively does
- + * in-place modification (string->number). */
- if (!tonumber(init, ra))
- luaG_runerror(L, LUA_QL("for") " initial value must be a number");
- else if (!tonumber(plimit, ra+1))
- luaG_runerror(L, LUA_QL("for") " limit must be a number");
- else if (!tonumber(pstep, ra+2))
- luaG_runerror(L, LUA_QL("for") " step must be a number");
- - setnvalue(ra, luai_numsub(nvalue(ra), nvalue(pstep)));
- + /* Step back one value (keep within integers if we can)
- + */
- + if (!( ttisint(ra) && ttisint(pstep) &&
- + try_subint( &ra->value.i, ivalue(ra), ivalue(pstep) ) )) {
- + /* don't use 'nvalue_fast()', values may be integer */
- + setnvalue(ra, luai_numsub(nvalue(ra), nvalue(pstep)));
- + }
- dojump(L, pc, GETARG_sBx(i));
- continue;
- }
- @@ -711,7 +935,7 @@ void luaV_execute (lua_State *L, int nex
- luaH_resizearray(L, h, last); /* pre-alloc it at once */
- for (; n > 0; n--) {
- TValue *val = ra+n;
- - setobj2t(L, luaH_setnum(L, h, last--), val);
- + setobj2t(L, luaH_setint(L, h, last--), val);
- luaC_barriert(L, h, val);
- }
- continue;
- --- a/src/lvm.h
- +++ b/src/lvm.h
- @@ -15,11 +15,9 @@
-
- #define tostring(L,o) ((ttype(o) == LUA_TSTRING) || (luaV_tostring(L, o)))
-
- -#define tonumber(o,n) (ttype(o) == LUA_TNUMBER || \
- - (((o) = luaV_tonumber(o,n)) != NULL))
- +#define tonumber(o,n) (ttisnumber(o) || (((o) = luaV_tonumber(o,n)) != NULL))
-
- -#define equalobj(L,o1,o2) \
- - (ttype(o1) == ttype(o2) && luaV_equalval(L, o1, o2))
- +#define equalobj(L,o1,o2) (ttype_ext_same(o1,o2) && luaV_equalval(L, o1, o2))
-
-
- LUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r);
- --- a/src/print.c
- +++ b/src/print.c
- @@ -14,6 +14,7 @@
- #include "lobject.h"
- #include "lopcodes.h"
- #include "lundump.h"
- +#include "lnum.h"
-
- #define PrintFunction luaU_print
-
- @@ -59,8 +60,16 @@ static void PrintConstant(const Proto* f
- case LUA_TBOOLEAN:
- printf(bvalue(o) ? "true" : "false");
- break;
- + case LUA_TINT:
- + printf(LUA_INTEGER_FMT,ivalue(o));
- + break;
- case LUA_TNUMBER:
- - printf(LUA_NUMBER_FMT,nvalue(o));
- +#ifdef LNUM_COMPLEX
- + // TBD: Do we get complex values here?
- + { lua_Number b= nvalue_img_fast(o);
- + printf( LUA_NUMBER_FMT "%s" LUA_NUMBER_FMT "i", nvalue_fast(o), b>=0 ? "+":"", b ); }
- +#endif
- + printf(LUA_NUMBER_FMT,nvalue_fast(o));
- break;
- case LUA_TSTRING:
- PrintString(rawtsvalue(o));
|