Cell cellArith(Op o, Cell c1, Cell c2) { again: if (c1.m_type == KindOfInt64) { for (;;) { if (c2.m_type == KindOfInt64) return o(c1.m_data.num, c2.m_data.num); if (c2.m_type == KindOfDouble) return o(c1.m_data.num, c2.m_data.dbl); c2 = numericConvHelper(c2); assert(c2.m_type == KindOfInt64 || c2.m_type == KindOfDouble); } } if (c1.m_type == KindOfDouble) { for (;;) { if (c2.m_type == KindOfDouble) return o(c1.m_data.dbl, c2.m_data.dbl); if (c2.m_type == KindOfInt64) return o(c1.m_data.dbl, c2.m_data.num); c2 = numericConvHelper(c2); assert(c2.m_type == KindOfInt64 || c2.m_type == KindOfDouble); } } if (c1.m_type == KindOfArray && c2.m_type == KindOfArray) { return make_tv<KindOfArray>(o(c1.m_data.parr, c2.m_data.parr)); } c1 = numericConvHelper(c1); assert(c1.m_type == KindOfInt64 || c1.m_type == KindOfDouble); goto again; }
Cell cellArithO(Op o, Check ck, Over ov, Cell c1, Cell c2) { if (c1.m_type == KindOfArray && c2.m_type == KindOfArray) { return cellArith(o, c1, c2); } auto ensure_num = [](Cell& c) { if (c.m_type != KindOfInt64 && c.m_type != KindOfDouble) { cellCopy(numericConvHelper(c), c); } }; ensure_num(c1); ensure_num(c2); auto both_ints = (c1.m_type == KindOfInt64 && c2.m_type == KindOfInt64); int64_t a = c1.m_data.num; int64_t b = c2.m_data.num; return (both_ints && ck(a,b)) ? ov(a,b) : cellArith(o, c1, c2); }