void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2, StkId res, TMS event) { if (!luaT_callbinTM(L, p1, p2, res, event)) { switch (event) { case TM_CONCAT: luaG_concaterror(L, p1, p2); case TM_IDIV: case TM_BAND: case TM_BOR: case TM_BXOR: case TM_SHL: case TM_SHR: case TM_BNOT: { lua_Number dummy; if (tonumber(p1, &dummy) && tonumber(p2, &dummy)) luaG_tointerror(L, p1, p2); /* else go through */ } default: luaG_aritherror(L, p1, p2); } } }
void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2, StkId res, TMS event) { if (!callbinTM(L, p1, p2, res, event)) { switch (event) { case TM_CONCAT: luaG_concaterror(L, p1, p2); /* call never returns, but to avoid warnings: *//* FALLTHROUGH */ case TM_BAND: case TM_BOR: case TM_BXOR: case TM_SHL: case TM_SHR: case TM_BNOT: { if (ttisnumber(p1) && ttisnumber(p2)) luaG_tointerror(L, p1, p2); else luaG_opinterror(L, p1, p2, "perform bitwise operation on"); } /* calls never return, but to avoid warnings: *//* FALLTHROUGH */ default: luaG_opinterror(L, p1, p2, "perform arithmetic on"); } } }
void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2, StkId res, TMS event) { TMS op = event; const StkId rb = p1; const StkId rc = p2; StkId ra = res; if (ttisvector2(rb) && ttisvector2(rc)) { lua_Float4 nb = v2value(rb), nc = v2value(rc); lua_Float4 r; switch (op) { case TM_ADD: PW2(addf); break; case TM_SUB: PW2(subf); break; case TM_MUL: PW2(mulf); break; case TM_DIV: if (nc.x==0.0 || nc.y==0.0) { luaG_runerror(L, "division by zero"); } PW2(divf); break; case TM_MOD: PW2(fmodf); break; case TM_POW: PW2(powf); break; case TM_UNM: r.x = -nb.x; r.y = -nb.y; break; default: lua_assert(0); break; } setv2value(ra, r); return; } else if (ttisvector3(rb) && ttisvector3(rc)) { lua_Float4 nb = v3value(rb), nc = v3value(rc); lua_Float4 r; switch (op) { case TM_ADD: PW3(addf); break; case TM_SUB: PW3(subf); break; case TM_MUL: PW3(mulf); break; case TM_DIV: if (nc.x==0.0 || nc.y==0.0 || nc.z==0.0) { luaG_runerror(L, "division by zero"); } PW3(divf); break; case TM_MOD: PW3(fmodf); break; case TM_POW: PW3(powf); break; case TM_UNM: r.x = -nb.x; r.y = -nb.y; r.z = -nb.z; break; default: lua_assert(0); break; } setv3value(ra, r); return; } else if (ttisvector4(rb) && ttisvector4(rc)) { lua_Float4 nb = v4value(rb), nc = v4value(rc); lua_Float4 r; switch (op) { case TM_ADD: PW4(addf); break; case TM_SUB: PW4(subf); break; case TM_MUL: PW4(mulf); break; case TM_DIV: if (nc.x==0.0 || nc.y==0.0 || nc.z==0.0 || nc.w==0.0) { luaG_runerror(L, "division by zero"); } PW4(divf); break; case TM_MOD: PW4(fmodf); break; case TM_POW: PW4(powf); break; case TM_UNM: r.x = -nb.x; r.y = -nb.y; r.z = -nb.z; r.w = -nb.w; break; default: lua_assert(0); break; } setv4value(ra, r); return; } else if (ttisvector2(rb) && ttisnumber(rc)) { lua_Float4 nb = v2value(rb); float nc = (float)nvalue(rc); lua_Float4 r; switch (op) { case TM_MUL: SCALAR2(mulf); break; case TM_ADD: SCALAR2(addf); break; case TM_SUB: SCALAR2(subf); break; case TM_DIV: if (nc==0.0) { luaG_runerror(L, "division by zero"); } SCALAR2(divf); break; case TM_MOD: SCALAR2(fmodf); break; case TM_POW: SCALAR2(powf); break; default: luaG_runerror(L, "Cannot use that op with vector2 and number"); } setv2value(ra, r); return; } else if (ttisvector3(rb) && ttisnumber(rc)) { lua_Float4 nb = v3value(rb); float nc = (float)nvalue(rc); lua_Float4 r; switch (op) { case TM_MUL: SCALAR3(mulf); break; case TM_ADD: SCALAR3(addf); break; case TM_SUB: SCALAR3(subf); break; case TM_DIV: if (nc==0.0) { luaG_runerror(L, "division by zero"); } SCALAR3(divf); break; case TM_MOD: SCALAR3(fmodf); break; case TM_POW: SCALAR3(powf); break; default: luaG_runerror(L, "Cannot use that op with vector3 and number"); } setv3value(ra, r); return; } else if (ttisvector4(rb) && ttisnumber(rc)) { lua_Float4 nb = v4value(rb); float nc = (float)nvalue(rc); lua_Float4 r; switch (op) { case TM_MUL: SCALAR4(mulf); break; case TM_ADD: SCALAR4(addf); break; case TM_SUB: SCALAR4(subf); break; case TM_DIV: if (nc==0.0) { luaG_runerror(L, "division by zero"); } SCALAR4(divf); break; case TM_MOD: SCALAR4(fmodf); break; case TM_POW: SCALAR4(powf); break; default: luaG_runerror(L, "Cannot use that op with vector4 and number"); } setv4value(ra, r); return; } else if (ttisnumber(rb) && ttisvector2(rc)) { lua_Float4 nb = v2value(rc); float nc = (float)nvalue(rb); lua_Float4 r; switch (op) { case TM_MUL: SCALAR2B(mulf); break; case TM_ADD: SCALAR2B(addf); break; case TM_SUB: SCALAR2B(subf); break; case TM_DIV: if (nb.x==0.0 || nb.y==0.0) { luaG_runerror(L, "division by zero"); } SCALAR2B(divf); break; case TM_POW: SCALAR2B(powf); break; default: luaG_runerror(L, "Cannot use that op with number and vector2"); } setv2value(ra, r); return; } else if (ttisnumber(rb) && ttisvector3(rc)) { lua_Float4 nb = v3value(rc); float nc = (float)nvalue(rb); lua_Float4 r; switch (op) { case TM_MUL: SCALAR3B(mulf); break; case TM_ADD: SCALAR3B(addf); break; case TM_SUB: SCALAR3B(subf); break; case TM_DIV: if (nb.x==0.0 || nb.y==0.0 || nb.z==0.0) { luaG_runerror(L, "division by zero"); } SCALAR3B(divf); break; case TM_POW: SCALAR3B(powf); break; default: luaG_runerror(L, "Cannot use that op with number and vector3"); } setv3value(ra, r); return; } else if (ttisnumber(rb) && ttisvector4(rc)) { lua_Float4 nb = v4value(rc); float nc = (float)nvalue(rb); lua_Float4 r; switch (op) { case TM_MUL: SCALAR4B(mulf); break; case TM_ADD: SCALAR4B(addf); break; case TM_SUB: SCALAR4B(subf); break; case TM_DIV: if (nb.x==0.0 || nb.y==0.0 || nb.z==0.0 || nb.w==0.0) { luaG_runerror(L, "division by zero"); } SCALAR4B(divf); break; case TM_POW: SCALAR4B(powf); break; default: luaG_runerror(L, "Cannot use that op with number and vector4"); } setv4value(ra, r); return; } else if (ttisquat(rb) && ttisquat(rc)) { lua_Float4 nb = qvalue(rb), nc = qvalue(rc); lua_Float4 r; switch (op) { case TM_MUL: r.w = nb.w*nc.w - nb.x*nc.x - nb.y*nc.y - nb.z*nc.z; r.x = nb.w*nc.x + nb.x*nc.w + nb.y*nc.z - nb.z*nc.y; r.y = nb.w*nc.y + nb.y*nc.w + nb.z*nc.x - nb.x*nc.z; r.z = nb.w*nc.z + nb.z*nc.w + nb.x*nc.y - nb.y*nc.x; break; default: luaG_runerror(L, "Cannot use that op with quat and quat"); } setqvalue(ra, r); return; } else if (ttisquat(rb) && ttisvector3(rc)) { lua_Float4 nb = qvalue(rb), nc = v3value(rc); lua_Float4 r; switch (op) { case TM_MUL: { float a=nb.w, b=nb.x, c=nb.y, d=nb.z; float mat[3][3] = { /* row major */ { a*a+b*b-c*c-d*d, 2*b*c-2*a*d , 2*b*d+2*a*c }, { 2*b*c+2*a*d , a*a-b*b+c*c-d*d, 2*c*d-2*a*b }, { 2*b*d-2*a*c , 2*c*d+2*a*b , a*a-b*b-c*c+d*d }, }; r.x = mat[0][0]*nc.x + mat[0][1]*nc.y + mat[0][2]*nc.z; r.y = mat[1][0]*nc.x + mat[1][1]*nc.y + mat[1][2]*nc.z; r.z = mat[2][0]*nc.x + mat[2][1]*nc.y + mat[2][2]*nc.z; } break; default: luaG_runerror(L, "Cannot use that op with quat and vector3"); } setv3value(ra, r); return; } if (!luaT_callbinTM(L, p1, p2, res, event)) { switch (event) { case TM_CONCAT: luaG_concaterror(L, p1, p2); /* call never returns, but to avoid warnings: *//* FALLTHROUGH */ case TM_BAND: case TM_BOR: case TM_BXOR: case TM_SHL: case TM_SHR: case TM_BNOT: { lua_Number dummy; if (tonumber(p1, &dummy) && tonumber(p2, &dummy)) luaG_tointerror(L, p1, p2); else luaG_opinterror(L, p1, p2, "perform bitwise operation on"); } /* calls never return, but to avoid warnings: *//* FALLTHROUGH */ default: luaG_opinterror(L, p1, p2, "perform arithmetic on"); } } }