⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 erl_arith.c

📁 OTP是开放电信平台的简称
💻 C
📖 第 1 页 / 共 4 页
字号:
	break;    case BIG_BIG:	break;    default:	p->freason = BADARITH;	return THE_NON_VALUE;    }    need = BIG_NEED_SIZE(MAX(big_size(arg1), big_size(arg2)) + 1);    hp = ArithAlloc(p, need);    arg1 = big_band(arg1, arg2, hp);    ASSERT(is_not_nil(arg1));    maybe_shrink(p, hp, arg1, need);    ArithCheck(p);    return arg1;}Eterm erts_bor(Process* p, Eterm arg1, Eterm arg2){    Eterm tmp_big1[2];    Eterm tmp_big2[2];    Eterm* hp;    int need;    switch (NUMBER_CODE(arg1, arg2)) {    case SMALL_BIG:	arg1 = small_to_big(signed_val(arg1), tmp_big1);	break;    case BIG_SMALL:	arg2 = small_to_big(signed_val(arg2), tmp_big2);	break;    case BIG_BIG:	break;    default:	p->freason = BADARITH;	return THE_NON_VALUE;    }    need = BIG_NEED_SIZE(MAX(big_size(arg1), big_size(arg2)) + 1);    hp = ArithAlloc(p, need);    arg1 = big_bor(arg1, arg2, hp);    ASSERT(is_not_nil(arg1));    maybe_shrink(p, hp, arg1, need);    ArithCheck(p);    return arg1;}Eterm erts_bxor(Process* p, Eterm arg1, Eterm arg2){    Eterm tmp_big1[2];    Eterm tmp_big2[2];    Eterm* hp;    int need;    switch (NUMBER_CODE(arg1, arg2)) {    case SMALL_BIG:	arg1 = small_to_big(signed_val(arg1), tmp_big1);	break;    case BIG_SMALL:	arg2 = small_to_big(signed_val(arg2), tmp_big2);	break;    case BIG_BIG:	break;    default:	p->freason = BADARITH;	return THE_NON_VALUE;    }    need = BIG_NEED_SIZE(MAX(big_size(arg1), big_size(arg2)) + 1);    hp = ArithAlloc(p, need);    arg1 = big_bxor(arg1, arg2, hp);    ASSERT(is_not_nil(arg1));    maybe_shrink(p, hp, arg1, need);    ArithCheck(p);    return arg1;}Eterm erts_bnot(Process* p, Eterm arg){    Eterm ret;    if (is_big(arg)) {	Uint need = BIG_NEED_SIZE(big_size(arg)+1);	Eterm* bigp = ArithAlloc(p, need);	ret = big_bnot(arg, bigp);	maybe_shrink(p, bigp, ret, need);	if (is_nil(ret)) {	    p->freason = SYSTEM_LIMIT;	    return NIL;	}	ArithCheck(p);    } else {	p->freason = BADARITH;	return NIL;    }    return ret;} #if defined(HEAP_FRAG_ELIM_TEST)#define ERTS_ARITH_FORCE_GC 0#define ERTS_NEED_GC(p, need) \  (ERTS_ARITH_FORCE_GC || (HEAP_LIMIT((p)) - HEAP_TOP((p))) <= (need))static ERTS_INLINE voidtrim_heap(Process* p, Eterm* hp, Eterm res){    if (is_immed(res)) {	ASSERT(p->heap <= hp && hp <= p->htop);	p->htop = hp;    } else {	Eterm* new_htop;	ASSERT(is_big(res));	new_htop = hp + bignum_header_arity(*hp) + 1;	ASSERT(p->heap <= new_htop && new_htop <= p->htop);	p->htop = new_htop;    }    ASSERT(p->heap <= p->htop && p->htop <= p->stop);}/* * The following are not allowed to be used here */#define erts_arith_shrink horrible error#define maybe_shrink horrible error#undef ArithAlloc#undef ArithCheck#define ArithAlloc horrible error#define ArithCheck horrible errorEtermerts_gc_mixed_plus(Process* p, Eterm* reg, Uint live){    Eterm arg1;    Eterm arg2;    Eterm tmp_big1[2];    Eterm tmp_big2[2];    Eterm res;    Eterm hdr;    FloatDef f1, f2;    dsize_t sz1, sz2, sz;    int need_heap;    Eterm* hp;    Sint ires;    arg1 = reg[live];    arg2 = reg[live+1];    ERTS_FP_CHECK_INIT(p);    switch (arg1 & _TAG_PRIMARY_MASK) {    case TAG_PRIMARY_IMMED1:	switch ((arg1 & _TAG_IMMED1_MASK) >> _TAG_PRIMARY_SIZE) {	case (_TAG_IMMED1_SMALL >> _TAG_PRIMARY_SIZE):	    switch (arg2 & _TAG_PRIMARY_MASK) {	    case TAG_PRIMARY_IMMED1:		switch ((arg2 & _TAG_IMMED1_MASK) >> _TAG_PRIMARY_SIZE) {		case (_TAG_IMMED1_SMALL >> _TAG_PRIMARY_SIZE):		    ires = signed_val(arg1) + signed_val(arg2);		    ASSERT(MY_IS_SSMALL(ires) == IS_SSMALL(ires));		    if (MY_IS_SSMALL(ires)) {			return make_small(ires);		    } else {			if (ERTS_NEED_GC(p, 2)) {			    erts_garbage_collect(p, 2, reg, live);			}			hp = p->htop;			p->htop += 2;			res = small_to_big(ires, hp);			return res;		    }		default:		badarith:		    p->freason = BADARITH;		    return THE_NON_VALUE;		}	    case TAG_PRIMARY_BOXED:		hdr = *boxed_val(arg2);		switch ((hdr & _TAG_HEADER_MASK) >> _TAG_PRIMARY_SIZE) {		case (_TAG_HEADER_POS_BIG >> _TAG_PRIMARY_SIZE):		case (_TAG_HEADER_NEG_BIG >> _TAG_PRIMARY_SIZE):		    if (arg1 == SMALL_ZERO) {			return arg2;		    }		    arg1 = small_to_big(signed_val(arg1), tmp_big1);		    goto do_big;		case (_TAG_HEADER_FLOAT >> _TAG_PRIMARY_SIZE):		    f1.fd = signed_val(arg1);		    GET_DOUBLE(arg2, f2);		    goto do_float;		default:		    goto badarith;		}	    }	default:	    goto badarith;	}    case TAG_PRIMARY_BOXED:	hdr = *boxed_val(arg1);	switch ((hdr & _TAG_HEADER_MASK) >> _TAG_PRIMARY_SIZE) {	case (_TAG_HEADER_POS_BIG >> _TAG_PRIMARY_SIZE):	case (_TAG_HEADER_NEG_BIG >> _TAG_PRIMARY_SIZE):	    switch (arg2 & _TAG_PRIMARY_MASK) {	    case (_TAG_IMMED1_SMALL >> _TAG_PRIMARY_SIZE):		switch ((arg2 & _TAG_IMMED1_MASK) >> _TAG_PRIMARY_SIZE) {		case (_TAG_IMMED1_SMALL >> _TAG_PRIMARY_SIZE):		    if (arg2 == SMALL_ZERO) {			return arg1;		    }		    arg2 = small_to_big(signed_val(arg2), tmp_big2);		    goto do_big;		default:		    goto badarith;		}	    case TAG_PRIMARY_BOXED:		hdr = *boxed_val(arg2);		switch ((hdr & _TAG_HEADER_MASK) >> _TAG_PRIMARY_SIZE) {		case (_TAG_HEADER_POS_BIG >> _TAG_PRIMARY_SIZE):		case (_TAG_HEADER_NEG_BIG >> _TAG_PRIMARY_SIZE):		do_big:		    sz1 = big_size(arg1);		    sz2 = big_size(arg2);		    sz = MAX(sz1, sz2)+1;		    need_heap = BIG_NEED_SIZE(sz);		    if (ERTS_NEED_GC(p, need_heap)) {			erts_garbage_collect(p, need_heap, reg, live+2);			if (arg1 != make_big(tmp_big1)) {			    arg1 = reg[live];			}			if (arg2 != make_big(tmp_big2)) {			    arg2 = reg[live+1];			}		    }		    hp = p->htop;		    p->htop += need_heap;		    res = big_plus(arg1, arg2, hp);		    trim_heap(p, hp, res);		    if (is_nil(res)) {			p->freason = SYSTEM_LIMIT;			return THE_NON_VALUE;		    }		    return res;		case (_TAG_HEADER_FLOAT >> _TAG_PRIMARY_SIZE):		    if (big_to_double(arg1, &f1.fd) < 0) {			goto badarith;		    }		    GET_DOUBLE(arg2, f2);		    goto do_float;		default:		    goto badarith;		}	    }	case (_TAG_HEADER_FLOAT >> _TAG_PRIMARY_SIZE):	    switch (arg2 & _TAG_PRIMARY_MASK) {	    case TAG_PRIMARY_IMMED1:		switch ((arg2 & _TAG_IMMED1_MASK) >> _TAG_PRIMARY_SIZE) {		case (_TAG_IMMED1_SMALL >> _TAG_PRIMARY_SIZE):		    GET_DOUBLE(arg1, f1);		    f2.fd = signed_val(arg2);		    goto do_float;		default:		    goto badarith;		}	    case TAG_PRIMARY_BOXED:		hdr = *boxed_val(arg2);		switch ((hdr & _TAG_HEADER_MASK) >> _TAG_PRIMARY_SIZE) {		case (_TAG_HEADER_POS_BIG >> _TAG_PRIMARY_SIZE):		case (_TAG_HEADER_NEG_BIG >> _TAG_PRIMARY_SIZE):		    GET_DOUBLE(arg1, f1);		    if (big_to_double(arg2, &f2.fd) < 0) {			goto badarith;		    }		    goto do_float;		case (_TAG_HEADER_FLOAT >> _TAG_PRIMARY_SIZE):		    GET_DOUBLE(arg1, f1);		    GET_DOUBLE(arg2, f2);		do_float:		    f1.fd = f1.fd + f2.fd;		    ERTS_FP_ERROR(p, f1.fd, goto badarith);		    if (ERTS_NEED_GC(p, FLOAT_SIZE_OBJECT)) {			erts_garbage_collect(p, FLOAT_SIZE_OBJECT, reg, live);		    }		    hp = p->htop;		    p->htop += FLOAT_SIZE_OBJECT;		    res = make_float(hp);		    PUT_DOUBLE(f1, hp);		    return res;		default:		    goto badarith;		}	    default:		goto badarith;	    }	}    default:	goto badarith;    }}Etermerts_gc_mixed_minus(Process* p, Eterm* reg, Uint live){    Eterm arg1;    Eterm arg2;    Eterm tmp_big1[2];    Eterm tmp_big2[2];    Eterm hdr;    Eterm res;    FloatDef f1, f2;    dsize_t sz1, sz2, sz;    int need_heap;    Eterm* hp;    Sint ires;    arg1 = reg[live];    arg2 = reg[live+1];    ERTS_FP_CHECK_INIT(p);    switch (arg1 & _TAG_PRIMARY_MASK) {    case TAG_PRIMARY_IMMED1:	switch ((arg1 & _TAG_IMMED1_MASK) >> _TAG_PRIMARY_SIZE) {	case (_TAG_IMMED1_SMALL >> _TAG_PRIMARY_SIZE):	    switch (arg2 & _TAG_PRIMARY_MASK) {	    case TAG_PRIMARY_IMMED1:		switch ((arg2 & _TAG_IMMED1_MASK) >> _TAG_PRIMARY_SIZE) {		case (_TAG_IMMED1_SMALL >> _TAG_PRIMARY_SIZE):		    ires = signed_val(arg1) - signed_val(arg2);		    ASSERT(MY_IS_SSMALL(ires) == IS_SSMALL(ires));		    if (MY_IS_SSMALL(ires)) {			return make_small(ires);		    } else {			if (ERTS_NEED_GC(p, 2)) {			    erts_garbage_collect(p, 2, reg, live);			}			hp = p->htop;			p->htop += 2;			res = small_to_big(ires, hp);			return res;		    }		default:		badarith:		    p->freason = BADARITH;		    return THE_NON_VALUE;		}	    case TAG_PRIMARY_BOXED:		hdr = *boxed_val(arg2);		switch ((hdr & _TAG_HEADER_MASK) >> _TAG_PRIMARY_SIZE) {		case (_TAG_HEADER_POS_BIG >> _TAG_PRIMARY_SIZE):		case (_TAG_HEADER_NEG_BIG >> _TAG_PRIMARY_SIZE):		    arg1 = small_to_big(signed_val(arg1), tmp_big1);		    goto do_big;		case (_TAG_HEADER_FLOAT >> _TAG_PRIMARY_SIZE):		    f1.fd = signed_val(arg1);		    GET_DOUBLE(arg2, f2);		    goto do_float;		default:		    goto badarith;		}	    }	default:	    goto badarith;	}    case TAG_PRIMARY_BOXED:	hdr = *boxed_val(arg1);	switch ((hdr & _TAG_HEADER_MASK) >> _TAG_PRIMARY_SIZE) {	case (_TAG_HEADER_POS_BIG >> _TAG_PRIMARY_SIZE):	case (_TAG_HEADER_NEG_BIG >> _TAG_PRIMARY_SIZE):	    switch (arg2 & _TAG_PRIMARY_MASK) {	    case (_TAG_IMMED1_SMALL >> _TAG_PRIMARY_SIZE):		switch ((arg2 & _TAG_IMMED1_MASK) >> _TAG_PRIMARY_SIZE) {		case (_TAG_IMMED1_SMALL >> _TAG_PRIMARY_SIZE):		    if (arg2 == SMALL_ZERO) {			return arg1;		    }		    arg2 = small_to_big(signed_val(arg2), tmp_big2);		do_big:		    sz1 = big_size(arg1);		    sz2 = big_size(arg2);		    sz = MAX(sz1, sz2)+1;		    need_heap = BIG_NEED_SIZE(sz);		    if (ERTS_NEED_GC(p, need_heap)) {			erts_garbage_collect(p, need_heap, reg, live+2);			if (arg1 != make_big(tmp_big1)) {			    arg1 = reg[live];			}			if (arg2 != make_big(tmp_big2)) {			    arg2 = reg[live+1];			}		    }		    hp = p->htop;		    p->htop += need_heap;		    res = big_minus(arg1, arg2, hp);                    trim_heap(p, hp, res);		    if (is_nil(res)) {			p->freason = SYSTEM_LIMIT;			return THE_NON_VALUE;		    }		    return res;		default:		    goto badarith;		}	    case TAG_PRIMARY_BOXED:		hdr = *boxed_val(arg2);		switch ((hdr & _TAG_HEADER_MASK) >> _TAG_PRIMARY_SIZE) {		case (_TAG_HEADER_POS_BIG >> _TAG_PRIMARY_SIZE):		case (_TAG_HEADER_NEG_BIG >> _TAG_PRIMARY_SIZE):		    goto do_big;		case (_TAG_HEADER_FLOAT >> _TAG_PRIMARY_SIZE):		    if (big_to_double(arg1, &f1.fd) < 0) {			goto badarith;		    }		    GET_DOUBLE(arg2, f2);		    goto do_float;		default:		    goto badarith;		}	    }	case (_TAG_HEADER_FLOAT >> _TAG_PRIMARY_SIZE):	    switch (arg2 & _TAG_PRIMARY_MASK) {	    case TAG_PRIMARY_IMMED1:		switch ((arg2 & _TAG_IMMED1_MASK) >> _TAG_PRIMARY_SIZE) {		case (_TAG_IMMED1_SMALL >> _TAG_PRIMARY_SIZE):		    GET_DOUBLE(arg1, f1);		    f2.fd = signed_val(arg2);		    goto do_float;		default:		    goto badarith;		}	    case TAG_PRIMARY_BOXED:		hdr = *boxed_val(arg2);		switch ((hdr & _TAG_HEADER_MASK) >> _TAG_PRIMARY_SIZE) {		case (_TAG_HEADER_POS_BIG >> _TAG_PRIMARY_SIZE):		case (_TAG_HEADER_NEG_BIG >> _TAG_PRIMARY_SIZE):		    GET_DOUBLE(arg1, f1);		    if (big_to_double(arg2, &f2.fd) < 0) {			goto badarith;		    }		    goto do_float;		case (_TAG_HEADER_FLOAT >> _TAG_PRIMARY_SIZE):		    GET_DOUBLE(arg1, f1);		    GET_DOUBLE(arg2, f2);		do_float:		    f1.fd = f1.fd - f2.fd;		    ERTS_FP_ERROR(p, f1.fd, goto badarith);		    if (ERTS_NEED_GC(p, FLOAT_SIZE_OBJECT)) {			erts_garbage_collect(p, FLOAT_SIZE_OBJECT, reg, live);		    }		    hp = p->htop;		    p->htop += FLOAT_SIZE_OBJECT;		    res = make_float(hp);		    PUT_DOUBLE(f1, hp);		    return res;		default:		    goto badarith;		}	    default:		goto badarith;	    }	}    default:	goto badarith;    }}Etermerts_gc_mixed_times(Process* p, Eterm* reg, Uint live){    Eterm arg1;    Eterm arg2;    Eterm tmp_big1[2];    Eterm tmp_big2[2];    Eterm hdr;    Eterm res;    FloatDef f1, f2;    dsize_t sz1, sz2, sz;    int need_heap;    Eterm* hp;    arg1 = reg[live];    arg2 = reg[live+1];    ERTS_FP_CHECK_INIT(p);    switch (arg1 & _TAG_PRIMARY_MASK) {    case TAG_PRIMARY_IMMED1:	switch ((arg1 & _TAG_IMMED1_MASK) >> _TAG_PRIMARY_SIZE) {	case (_TAG_IMMED1_SMALL >> _TAG_PRIMARY_SIZE):	    switch (arg2 & _TAG_PRIMARY_MASK) {	    case TAG_PRIMARY_IMMED1:		switch ((arg2 & _TAG_IMMED1_MASK) >> _TAG_PRIMARY_SIZE) {		case (_TAG_IMMED1_SMALL >> _TAG_PRIMARY_SIZE):		    if ((arg1 == SMALL_ZERO) || (arg2 == SMALL_ZERO)) {			return(SMALL_ZERO);		    } else if (arg1 == SMALL_ONE) {			return(arg2);		    } else if (arg2 == SMALL_ONE) {			return(arg1);		    } else {			Eterm big_res[3];			/*			 * The following code is optimized for the case that			 * result is small (which should be the most common case			 * in practice).			 */			arg1 = small_to_big(signed_val(arg1), tmp_big1);			arg2 = small_to_big(signed_val(arg2), tmp_big2);			res = big_times(arg1, arg2, big_res);			if (is_small(res)) {			    return res;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -