/* '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. */ #ifdef LUA_TINT if (ttisint(o)) { lua_integer2str( s, ivalue(o) ); return; } #endif 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 }
static int addk (FuncState *fs, TValue *k, TValue *v) { lua_State *L = fs->L; TValue *idx = luaH_set(L, fs->h, k); Proto *f = fs->f; int oldsize = f->sizek; 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 */ 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++]); setobj(L, &f->k[fs->nk], v); luaC_barrier(L, f, v); return fs->nk++; } }
static inline int arith_mode1( const TValue *rb ) { return ttisint(rb) ? TK_INT : ttiscomplex(rb) ? TK_NUMBER2 : ttisnumber(rb) ? TK_NUMBER : 0; }
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; }
/* 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. */ #ifdef LUA_TINT 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); } } #endif /* 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); }