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

📄 erl_arith.c

📁 OTP是开放电信平台的简称
💻 C
📖 第 1 页 / 共 4 页
字号:
			} else {			    /*			     * The result is a a big number.			     * Allocate a heap fragment and copy the result.			     * Be careful to allocate exactly what we need			     * to not leave any holes.			     */			    Uint arity;			    Uint need;			    			    ASSERT(is_big(res));			    hdr = big_res[0];			    arity = bignum_header_arity(hdr);			    ASSERT(arity == 1 || arity == 2);			    need = arity + 1;			    if (ERTS_NEED_GC(p, need)) {				erts_garbage_collect(p, need, reg, live);			    }			    hp = p->htop;			    p->htop += need;			    res = make_big(hp);			    *hp++ = hdr;			    *hp++ = big_res[1];			    if (arity > 1) {				*hp = big_res[2];			    }			    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(SMALL_ZERO);		    if (arg1 == SMALL_ONE)			return(arg2);		    arg1 = small_to_big(signed_val(arg1), tmp_big1);		    sz = 2 + big_size(arg2);		    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(SMALL_ZERO);		    if (arg2 == SMALL_ONE)			return(arg1);		    arg2 = small_to_big(signed_val(arg2), tmp_big2);		    sz = 2 + big_size(arg1);		    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):		    sz1 = big_size(arg1);		    sz2 = big_size(arg2);		    sz = sz1 + sz2;		do_big:		    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_times(arg1, arg2, hp);                    trim_heap(p, hp, res);		    /*		     * Note that the result must be big in this case, since		     * at least one operand was big to begin with, and		     * the absolute value of the other is > 1.		     */		    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_div(Process* p, Eterm* reg, Uint live){    Eterm arg1;    Eterm arg2;    FloatDef f1, f2;    Eterm* hp;    Eterm hdr;    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):		    f1.fd = signed_val(arg1);		    f2.fd = signed_val(arg2);		    goto do_float;		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):		    f1.fd = signed_val(arg1);		    if (big_to_double(arg2, &f2.fd) < 0) {			goto badarith;		    }		    goto do_float;		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 (big_to_double(arg1, &f1.fd) < 0) {			goto badarith;		    }		    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):		    if (big_to_double(arg1, &f1.fd) < 0 ||			big_to_double(arg2, &f2.fd) < 0) {			goto badarith;		    }		    goto do_float;		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;		    PUT_DOUBLE(f1, hp);		    return make_float(hp);		default:		    goto badarith;		}	    default:		goto badarith;	    }	}    default:	goto badarith;    }}Etermerts_gc_int_div(Process* p, Eterm* reg, Uint live){    Eterm arg1;    Eterm arg2;    Eterm tmp_big1[2];    Eterm tmp_big2[2];    int ires;    arg1 = reg[live];    arg2 = reg[live+1];    switch (NUMBER_CODE(arg1, arg2)) {    case SMALL_SMALL:	/* This case occurs if the most negative fixnum is divided by -1. */	ASSERT(arg2 == make_small(-1));	arg1 = small_to_big(signed_val(arg1), tmp_big1);	/*FALLTHROUGH*/    case BIG_SMALL:	arg2 = small_to_big(signed_val(arg2), tmp_big2);	goto L_big_div;    case SMALL_BIG:	if (arg1 != make_small(MIN_SMALL)) {	    return SMALL_ZERO;	}	arg1 = small_to_big(signed_val(arg1), tmp_big1);	/*FALLTHROUGH*/    case BIG_BIG:    L_big_div:	ires = big_ucomp(arg1, arg2);	if (ires < 0) {	    arg1 = SMALL_ZERO;	} else if (ires == 0) {	    arg1 = (big_sign(arg1) == big_sign(arg2)) ?		SMALL_ONE : SMALL_MINUS_ONE;	} else {	    Eterm* hp;	    int i = big_size(arg1);	    Uint need;	    ires = big_size(arg2);	    need = BIG_NEED_SIZE(i-ires+1) + BIG_NEED_SIZE(i);	    if (ERTS_NEED_GC(p, need)) {		erts_garbage_collect(p, need, 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;	    arg1 = big_div(arg1, arg2, hp);	    trim_heap(p, hp, arg1);	    if (is_nil(arg1)) {		p->freason = SYSTEM_LIMIT;		return THE_NON_VALUE;	    }	}	return arg1;    default:	p->freason = BADARITH;	return THE_NON_VALUE;    }}Etermerts_gc_int_rem(Process* p, Eterm* reg, Uint live){    Eterm arg1;    Eterm arg2;    Eterm tmp_big1[2];    Eterm tmp_big2[2];    int ires;    arg1 = reg[live];    arg2 = reg[live+1];    switch (NUMBER_CODE(arg1, arg2)) {    case BIG_SMALL:	arg2 = small_to_big(signed_val(arg2), tmp_big2);	goto L_big_rem;    case SMALL_BIG:	if (arg1 != make_small(MIN_SMALL)) {	    return arg1;	}	arg1 = small_to_big(signed_val(arg1), tmp_big1);	/*FALLTHROUGH*/    case BIG_BIG:    L_big_rem:	ires = big_ucomp(arg1, arg2);	if (ires == 0) {	    arg1 = SMALL_ZERO;	} else if (ires > 0) {	    Eterm* hp;	    Uint need = BIG_NEED_SIZE(big_size(arg1));	    if (ERTS_NEED_GC(p, need)) {		erts_garbage_collect(p, need, 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;	    arg1 = big_rem(arg1, arg2, hp);	    trim_heap(p, hp, arg1);	    if (is_nil(arg1)) {		p->freason = SYSTEM_LIMIT;		return THE_NON_VALUE;	    }	}	return arg1;    default:	p->freason = BADARITH;	return THE_NON_VALUE;    }}#define DEFINE_GC_LOGIC_FUNC(func)						\Eterm erts_gc_##func(Process* p, Eterm* reg, Uint live)				\{										\    Eterm arg1;									\    Eterm arg2;									\    Eterm tmp_big1[2];								\    Eterm tmp_big2[2];								\    Eterm* hp;									\    int need;									\										\    arg1 = reg[live];								\    arg2 = reg[live+1];								\    switch (NUMBER_CODE(arg1, arg2)) {						\    case SMALL_BIG:								\	arg1 = small_to_big(signed_val(arg1), tmp_big1);			\	need = BIG_NEED_SIZE(big_size(arg2) + 1);				\	if (ERTS_NEED_GC(p, need)) {						\	    erts_garbage_collect(p, need, reg, live+2);				\	    arg2 = reg[live+1];							\	}									\	break;									\    case BIG_SMALL:								\	arg2 = small_to_big(signed_val(arg2), tmp_big2);			\	need = BIG_NEED_SIZE(big_size(arg1) + 1);				\	if (ERTS_NEED_GC(p, need)) {						\	    erts_garbage_collect(p, need, reg, live+2);				\	    arg1 = reg[live];							\	}									\	break;									\    case BIG_BIG:								\	need = BIG_NEED_SIZE(MAX(big_size(arg1), big_size(arg2)) + 1);		\	if (ERTS_NEED_GC(p, need)) {						\	    erts_garbage_collect(p, need, reg, live+2);				\	    arg1 = reg[live];							\	    arg2 = reg[live+1];							\	}									\	break;									\    default:									\	p->freason = BADARITH;							\	return THE_NON_VALUE;							\    }										\    hp = p->htop;								\    p->htop += need;								\    arg1 = big_##func(arg1, arg2, hp);						\    trim_heap(p, hp, arg1);							\    return arg1;								\}DEFINE_GC_LOGIC_FUNC(band)DEFINE_GC_LOGIC_FUNC(bor)DEFINE_GC_LOGIC_FUNC(bxor)Eterm erts_gc_bnot(Process* p, Eterm* reg, Uint live){    Eterm result;    Eterm arg;    Uint need;    Eterm* bigp;    arg = reg[live];    if (is_not_big(arg)) {	p->freason = BADARITH;	return NIL;    } else {	need = BIG_NEED_SIZE(big_size(arg)+1);	if (ERTS_NEED_GC(p, need)) {	    erts_garbage_collect(p, need, reg, live+1);	    arg = reg[live];	}	bigp = p->htop;	p->htop += need;	result = big_bnot(arg, bigp);	trim_heap(p, bigp, result);	if (is_nil(result)) {	    p->freason = SYSTEM_LIMIT;	    return NIL;	}    }    return result;} #endif

⌨️ 快捷键说明

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