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

📄 value.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 1994 David I. Bell * Permission is granted to use, distribute, or modify this source, * provided that this copyright notice remains intact. * * Generic value manipulation routines. */#include "value.h"#include "opcodes.h"#include "func.h"#include "symbol.h"#include "string.h"/* * Free a value and set its type to undefined. */voidfreevalue(vp)	register VALUE *vp;	/* value to be freed */{	int type;		/* type of value being freed */	type = vp->v_type;	vp->v_type = V_NULL;	switch (type) {		case V_NULL:		case V_ADDR:		case V_FILE:			break;		case V_STR:			if (vp->v_subtype == V_STRALLOC)				free(vp->v_str);			break;		case V_NUM:			qfree(vp->v_num);			break;		case V_COM:			comfree(vp->v_com);			break;		case V_MAT:			matfree(vp->v_mat);			break;		case V_LIST:			listfree(vp->v_list);			break;		case V_ASSOC:			assocfree(vp->v_assoc);			break;		case V_OBJ:			objfree(vp->v_obj);			break;		default:			math_error("Freeing unknown value type");	}	vp->v_subtype = V_NOSUBTYPE;}/* * Copy a value from one location to another. * This overwrites the specified new value without checking it. */voidcopyvalue(oldvp, newvp)	register VALUE *oldvp;		/* value to be copied from */	register VALUE *newvp;		/* value to be copied into */{	newvp->v_type = V_NULL;	switch (oldvp->v_type) {		case V_NULL:			break;		case V_FILE:			newvp->v_file = oldvp->v_file;			break;		case V_NUM:			newvp->v_num = qlink(oldvp->v_num);			break;		case V_COM:			newvp->v_com = clink(oldvp->v_com);			break;		case V_STR:			newvp->v_str = oldvp->v_str;			if (oldvp->v_subtype == V_STRALLOC) {				newvp->v_str = (char *)malloc(strlen(oldvp->v_str) + 1);				if (newvp->v_str == NULL)					math_error("Cannot get memory for string copy");				strcpy(newvp->v_str, oldvp->v_str);			}			break;		case V_MAT:			newvp->v_mat = matcopy(oldvp->v_mat);			break;		case V_LIST:			newvp->v_list = listcopy(oldvp->v_list);			break;		case V_ASSOC:			newvp->v_assoc = assoccopy(oldvp->v_assoc);			break;		case V_ADDR:			newvp->v_addr = oldvp->v_addr;			break;		case V_OBJ:			newvp->v_obj = objcopy(oldvp->v_obj);			break;		default:			math_error("Copying unknown value type");	}	if (oldvp->v_type == V_STR) {		newvp->v_subtype = oldvp->v_subtype;	} else {		newvp->v_subtype = V_NOSUBTYPE;	}	newvp->v_type = oldvp->v_type;}/* * Negate an arbitrary value. * Result is placed in the indicated location. */voidnegvalue(vp, vres)	VALUE *vp, *vres;{	vres->v_type = V_NULL;	switch (vp->v_type) {		case V_NUM:			vres->v_num = qneg(vp->v_num);			vres->v_type = V_NUM;			return;		case V_COM:			vres->v_com = cneg(vp->v_com);			vres->v_type = V_COM;			return;		case V_MAT:			vres->v_mat = matneg(vp->v_mat);			vres->v_type = V_MAT;			return;		case V_OBJ:			*vres = objcall(OBJ_NEG, vp, NULL_VALUE, NULL_VALUE);			return;		default:			math_error("Illegal value for negation");	}}/* * Add two arbitrary values together. * Result is placed in the indicated location. */voidaddvalue(v1, v2, vres)	VALUE *v1, *v2, *vres;{	COMPLEX *c;	vres->v_type = V_NULL;	switch (TWOVAL(v1->v_type, v2->v_type)) {		case TWOVAL(V_NUM, V_NUM):			vres->v_num = qadd(v1->v_num, v2->v_num);			vres->v_type = V_NUM;			return;		case TWOVAL(V_COM, V_NUM):			vres->v_com = caddq(v1->v_com, v2->v_num);			vres->v_type = V_COM;			return;		case TWOVAL(V_NUM, V_COM):			vres->v_com = caddq(v2->v_com, v1->v_num);			vres->v_type = V_COM;			return;		case TWOVAL(V_COM, V_COM):			vres->v_com = cadd(v1->v_com, v2->v_com);			vres->v_type = V_COM;			c = vres->v_com;			if (!cisreal(c))				return;			vres->v_num = qlink(c->real);			vres->v_type = V_NUM;			comfree(c);			return;		case TWOVAL(V_MAT, V_MAT):			vres->v_mat = matadd(v1->v_mat, v2->v_mat);			vres->v_type = V_MAT;			return;		default:			if ((v1->v_type != V_OBJ) && (v2->v_type != V_OBJ))				math_error("Non-compatible values for add");			*vres = objcall(OBJ_ADD, v1, v2, NULL_VALUE);			return;	}}/* * Subtract one arbitrary value from another one. * Result is placed in the indicated location. */voidsubvalue(v1, v2, vres)	VALUE *v1, *v2, *vres;{	COMPLEX *c;	vres->v_type = V_NULL;	switch (TWOVAL(v1->v_type, v2->v_type)) {		case TWOVAL(V_NUM, V_NUM):			vres->v_num = qsub(v1->v_num, v2->v_num);			vres->v_type = V_NUM;			return;		case TWOVAL(V_COM, V_NUM):			vres->v_com = csubq(v1->v_com, v2->v_num);			vres->v_type = V_COM;			return;		case TWOVAL(V_NUM, V_COM):			c = csubq(v2->v_com, v1->v_num);			vres->v_com = cneg(c);			comfree(c);			vres->v_type = V_COM;			return;		case TWOVAL(V_COM, V_COM):			vres->v_com = csub(v1->v_com, v2->v_com);			vres->v_type = V_COM;			c = vres->v_com;			if (!cisreal(c))				return;			vres->v_num = qlink(c->real);			vres->v_type = V_NUM;			comfree(c);			return;		case TWOVAL(V_MAT, V_MAT):			vres->v_mat = matsub(v1->v_mat, v2->v_mat);			vres->v_type = V_MAT;			return;		default:			if ((v1->v_type != V_OBJ) && (v2->v_type != V_OBJ))				math_error("Non-compatible values for subtract");			*vres = objcall(OBJ_SUB, v1, v2, NULL_VALUE);			return;	}}/* * Multiply two arbitrary values together. * Result is placed in the indicated location. */voidmulvalue(v1, v2, vres)	VALUE *v1, *v2, *vres;{	COMPLEX *c;	vres->v_type = V_NULL;	switch (TWOVAL(v1->v_type, v2->v_type)) {		case TWOVAL(V_NUM, V_NUM):			vres->v_num = qmul(v1->v_num, v2->v_num);			vres->v_type = V_NUM;			return;		case TWOVAL(V_COM, V_NUM):			vres->v_com = cmulq(v1->v_com, v2->v_num);			vres->v_type = V_COM;			break;		case TWOVAL(V_NUM, V_COM):			vres->v_com = cmulq(v2->v_com, v1->v_num);			vres->v_type = V_COM;			break;		case TWOVAL(V_COM, V_COM):			vres->v_com = cmul(v1->v_com, v2->v_com);			vres->v_type = V_COM;			break;		case TWOVAL(V_MAT, V_MAT):			vres->v_mat = matmul(v1->v_mat, v2->v_mat);			vres->v_type = V_MAT;			return;		case TWOVAL(V_MAT, V_NUM):		case TWOVAL(V_MAT, V_COM):			vres->v_mat = matmulval(v1->v_mat, v2);			vres->v_type = V_MAT;			return;		case TWOVAL(V_NUM, V_MAT):		case TWOVAL(V_COM, V_MAT):			vres->v_mat = matmulval(v2->v_mat, v1);			vres->v_type = V_MAT;			return;		default:			if ((v1->v_type != V_OBJ) && (v2->v_type != V_OBJ))				math_error("Non-compatible values for multiply");			*vres = objcall(OBJ_MUL, v1, v2, NULL_VALUE);			return;	}	c = vres->v_com;	if (cisreal(c)) {		vres->v_num = qlink(c->real);		vres->v_type = V_NUM;		comfree(c);	}}/* * Square an arbitrary value. * Result is placed in the indicated location. */voidsquarevalue(vp, vres)	VALUE *vp, *vres;{	COMPLEX *c;	vres->v_type = V_NULL;	switch (vp->v_type) {		case V_NUM:			vres->v_num = qsquare(vp->v_num);			vres->v_type = V_NUM;			return;		case V_COM:			vres->v_com = csquare(vp->v_com);			vres->v_type = V_COM;			c = vres->v_com;			if (!cisreal(c))				return;			vres->v_num = qlink(c->real);			vres->v_type = V_NUM;			comfree(c);			return;		case V_MAT:			vres->v_mat = matsquare(vp->v_mat);			vres->v_type = V_MAT;			return;		case V_OBJ:			*vres = objcall(OBJ_SQUARE, vp, NULL_VALUE, NULL_VALUE);			return;		default:			math_error("Illegal value for squaring");	}}/* * Invert an arbitrary value. * Result is placed in the indicated location. */voidinvertvalue(vp, vres)	VALUE *vp, *vres;{	vres->v_type = V_NULL;	switch (vp->v_type) {		case V_NUM:			vres->v_num = qinv(vp->v_num);			vres->v_type = V_NUM;			return;		case V_COM:			vres->v_com = cinv(vp->v_com);			vres->v_type = V_COM;			return;		case V_MAT:			vres->v_mat = matinv(vp->v_mat);			vres->v_type = V_MAT;			return;		case V_OBJ:			*vres = objcall(OBJ_INV, vp, NULL_VALUE, NULL_VALUE);			return;		default:			math_error("Illegal value for inverting");	}}/* * Round an arbitrary value to the specified number of decimal places. * Result is placed in the indicated location. */voidroundvalue(v1, v2, vres)	VALUE *v1, *v2, *vres;{	long places = -1;	NUMBER *q;	COMPLEX *c;	switch (v2->v_type) {		case V_NUM:			q = v2->v_num;			if (qisfrac(q) || zisbig(q->num))				math_error("Bad number of places for round");			places = qtoi(q);			break;		case V_INT:			places = v2->v_int;			break;		default:			math_error("Bad value type for places in round");	}	if (places < 0)		math_error("Negative number of places in round");	vres->v_type = V_NULL;	switch (v1->v_type) {		case V_NUM:			if (qisint(v1->v_num))				vres->v_num = qlink(v1->v_num);			else				vres->v_num = qround(v1->v_num, places);			vres->v_type = V_NUM;			return;		case V_COM:			if (cisint(v1->v_com)) {				vres->v_com = clink(v1->v_com);				vres->v_type = V_COM;				return;			}			vres->v_com = cround(v1->v_com, places);			vres->v_type = V_COM;			c = vres->v_com;			if (cisreal(c)) {				vres->v_num = qlink(c->real);				vres->v_type = V_NUM;				comfree(c);			}			return;		case V_MAT:			vres->v_mat = matround(v1->v_mat, places);			vres->v_type = V_MAT;			return;		case V_OBJ:			*vres = objcall(OBJ_ROUND, v1, v2, NULL_VALUE);			return;		default:			math_error("Illegal value for round");	}}/* * Round an arbitrary value to the specified number of binary places. * Result is placed in the indicated location. */voidbroundvalue(v1, v2, vres)	VALUE *v1, *v2, *vres;{	long places = -1;	NUMBER *q;	COMPLEX *c;	switch (v2->v_type) {		case V_NUM:			q = v2->v_num;			if (qisfrac(q) || zisbig(q->num))				math_error("Bad number of places for bround");			places = qtoi(q);			break;		case V_INT:			places = v2->v_int;			break;		default:			math_error("Bad value type for places in bround");	}	if (places < 0)		math_error("Negative number of places in bround");	vres->v_type = V_NULL;	switch (v1->v_type) {		case V_NUM:			if (qisint(v1->v_num))				vres->v_num = qlink(v1->v_num);			else				vres->v_num = qbround(v1->v_num, places);			vres->v_type = V_NUM;			return;		case V_COM:			if (cisint(v1->v_com)) {				vres->v_com = clink(v1->v_com);				vres->v_type = V_COM;				return;			}			vres->v_com = cbround(v1->v_com, places);			vres->v_type = V_COM;			c = vres->v_com;			if (cisreal(c)) {				vres->v_num = qlink(c->real);				vres->v_type = V_NUM;				comfree(c);			}			return;		case V_MAT:			vres->v_mat = matbround(v1->v_mat, places);			vres->v_type = V_MAT;			return;		case V_OBJ:			*vres = objcall(OBJ_BROUND, v1, v2, NULL_VALUE);			return;		default:			math_error("Illegal value for bround");	}}/* * Take the integer part of an arbitrary value. * Result is placed in the indicated location. */voidintvalue(vp, vres)	VALUE *vp, *vres;{	COMPLEX *c;	vres->v_type = V_NULL;	switch (vp->v_type) {		case V_NUM:			if (qisint(vp->v_num))				vres->v_num = qlink(vp->v_num);			else				vres->v_num = qint(vp->v_num);			vres->v_type = V_NUM;			return;		case V_COM:			if (cisint(vp->v_com)) {				vres->v_com = clink(vp->v_com);				vres->v_type = V_COM;				return;			}			vres->v_com = cint(vp->v_com);			vres->v_type = V_COM;			c = vres->v_com;			if (cisreal(c)) {				vres->v_num = qlink(c->real);				vres->v_type = V_NUM;				comfree(c);			}			return;		case V_MAT:			vres->v_mat = matint(vp->v_mat);			vres->v_type = V_MAT;			return;		case V_OBJ:			*vres = objcall(OBJ_INT, vp, NULL_VALUE, NULL_VALUE);			return;		default:			math_error("Illegal value for int");	}}/* * Take the fractional part of an arbitrary value. * Result is placed in the indicated location. */voidfracvalue(vp, vres)	VALUE *vp, *vres;{	vres->v_type = V_NULL;	switch (vp->v_type) {		case V_NUM:			if (qisint(vp->v_num))				vres->v_num = qlink(&_qzero_);			else				vres->v_num = qfrac(vp->v_num);			vres->v_type = V_NUM;			return;		case V_COM:			if (cisint(vp->v_com)) {				vres->v_num = clink(&_qzero_);				vres->v_type = V_NUM;				return;			}			vres->v_com = cfrac(vp->v_com);			vres->v_type = V_COM;			return;		case V_MAT:			vres->v_mat = matfrac(vp->v_mat);			vres->v_type = V_MAT;			return;		case V_OBJ:			*vres = objcall(OBJ_FRAC, vp, NULL_VALUE, NULL_VALUE);			return;		default:			math_error("Illegal value for frac function");	}}/* * Increment an arbitrary value by one. * Result is placed in the indicated location. */voidincvalue(vp, vres)	VALUE *vp, *vres;{	switch (vp->v_type) {		case V_NUM:			vres->v_num = qinc(vp->v_num);			vres->v_type = V_NUM;			return;		case V_COM:			vres->v_com = caddq(vp->v_com, &_qone_);			vres->v_type = V_COM;			return;		case V_OBJ:			*vres = objcall(OBJ_INC, vp, NULL_VALUE, NULL_VALUE);			return;		default:			math_error("Illegal value for incrementing");	}}/* * Decrement an arbitrary value by one. * Result is placed in the indicated location. */voiddecvalue(vp, vres)	VALUE *vp, *vres;{	switch (vp->v_type) {		case V_NUM:			vres->v_num = qdec(vp->v_num);			vres->v_type = V_NUM;			return;		case V_COM:			vres->v_com = caddq(vp->v_com, &_qnegone_);			vres->v_type = V_COM;			return;		case V_OBJ:			*vres = objcall(OBJ_DEC, vp, NULL_VALUE, NULL_VALUE);			return;		default:			math_error("Illegal value for decrementing");	}}/* * Produce the 'conjugate' of an arbitrary value. * Result is placed in the indicated location. * (Example: complex conjugate.) */voidconjvalue(vp, vres)	VALUE *vp, *vres;{	vres->v_type = V_NULL;	switch (vp->v_type) {		case V_NUM:			vres->v_num = qlink(vp->v_num);			vres->v_type = V_NUM;			return;		case V_COM:			vres->v_com = comalloc();			vres->v_com->real = qlink(vp->v_com->real);			vres->v_com->imag = qneg(vp->v_com->imag);			vres->v_type = V_COM;			return;		case V_MAT:			vres->v_mat = matconj(vp->v_mat);			vres->v_type = V_MAT;			return;		case V_OBJ:			*vres = objcall(OBJ_CONJ, vp, NULL_VALUE, NULL_VALUE);			return;		default:			math_error("Illegal value for conjugation");	}}/* * Take the square root of an arbitrary value within the specified error. * Result is placed in the indicated location. */voidsqrtvalue(v1, v2, vres)	VALUE *v1, *v2, *vres;{	NUMBER *q, *tmp;	COMPLEX *c;	if (v2->v_type != V_NUM)		math_error("Non-real epsilon for sqrt");	q = v2->v_num;	if (qisneg(q) || qiszero(q))		math_error("Illegal epsilon value for sqrt");	switch (v1->v_type) {		case V_NUM:			if (!qisneg(v1->v_num)) {				vres->v_num = qsqrt(v1->v_num, q);				vres->v_type = V_NUM;				return;			}			tmp = qneg(v1->v_num);			c = comalloc();			c->imag = qsqrt(tmp, q);			qfree(tmp);			vres->v_com = c;

⌨️ 快捷键说明

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