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

📄 erl_arith.c

📁 OTP是开放电信平台的简称
💻 C
📖 第 1 页 / 共 4 页
字号:
		do_big:		    sz1 = big_size(arg1);		    sz2 = big_size(arg2);		    sz = MAX(sz1, sz2)+1;		    need_heap = BIG_NEED_SIZE(sz);		    hp = ArithAlloc(p, need_heap);		    res = big_minus(arg1, arg2, hp);		    if (is_nil(res)) {			erts_arith_shrink(p, hp);			p->freason = SYSTEM_LIMIT;			return THE_NON_VALUE;		    }                    maybe_shrink(p, hp, res, need_heap);		    ArithCheck(p);		    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);		    hp = ArithAlloc(p, FLOAT_SIZE_OBJECT);		    res = make_float(hp);		    ArithCheck(p);		    PUT_DOUBLE(f1, hp);		    return res;		default:		    goto badarith;		}	    default:		goto badarith;	    }	}    default:	goto badarith;    }}Etermerts_mixed_times(Process* p, 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;    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;			} 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;			    			    ASSERT(is_big(res));			    hdr = big_res[0];			    arity = bignum_header_arity(hdr);			    ASSERT(arity == 1 || arity == 2);			    hp = ArithAlloc(p, arity+1);			    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);                    hp = ArithAlloc(p, need_heap);		    res = big_times(arg1, arg2, hp);		    /*		     * 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)) {			erts_arith_shrink(p, hp);			p->freason = SYSTEM_LIMIT;			return THE_NON_VALUE;		    }                    maybe_shrink(p, hp, res, need_heap);                    ArithCheck(p);		    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);		    hp = ArithAlloc(p, FLOAT_SIZE_OBJECT);		    res = make_float(hp);		    ArithCheck(p);		    PUT_DOUBLE(f1, hp);		    return res;		default:		    goto badarith;		}	    default:		goto badarith;	    }	}    default:	goto badarith;    }}Etermerts_mixed_div(Process* p, Eterm arg1, Eterm arg2){    FloatDef f1, f2;    Eterm* hp;    Eterm hdr;    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);		    hp = ArithAlloc(p, FLOAT_SIZE_OBJECT);		    PUT_DOUBLE(f1, hp);		    ArithCheck(p);		    return make_float(hp);		default:		    goto badarith;		}	    default:		goto badarith;	    }	}    default:	goto badarith;    }}Etermerts_int_div(Process* p, Eterm arg1, Eterm arg2){    Eterm tmp_big1[2];    Eterm tmp_big2[2];    int ires;    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);	    hp = ArithAlloc(p, need);	    arg1 = big_div(arg1, arg2, hp);	    if (is_nil(arg1)) {		erts_arith_shrink(p, hp);		p->freason = SYSTEM_LIMIT;		return THE_NON_VALUE;	    }	    maybe_shrink(p, hp, arg1, need);	    ArithCheck(p);	}	return arg1;    default:	p->freason = BADARITH;	return THE_NON_VALUE;    }}Etermerts_int_rem(Process* p, Eterm arg1, Eterm arg2){    Eterm tmp_big1[2];    Eterm tmp_big2[2];    int ires;    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) {	    Uint need = BIG_NEED_SIZE(big_size(arg1));	    Eterm* hp = ArithAlloc(p, need);	    arg1 = big_rem(arg1, arg2, hp);	    if (is_nil(arg1)) {		erts_arith_shrink(p, hp);		p->freason = SYSTEM_LIMIT;		return THE_NON_VALUE;	    }	    maybe_shrink(p, hp, arg1, need);	    ArithCheck(p);	}	return arg1;    default:	p->freason = BADARITH;	return THE_NON_VALUE;    }}Eterm erts_band(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);

⌨️ 快捷键说明

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