Пример #1
0
void
bignum_float(void)
{
	double d;
	d = convert_rational_to_double(pop());
	push_double(d);
}
Пример #2
0
void
add_numbers(void)
{
	double a, b;

	if (isrational(stack[tos - 1]) && isrational(stack[tos - 2])) {
		qadd();
		return;
	}

	save();

	p2 = pop();
	p1 = pop();

	if (isdouble(p1))
		a = p1->u.d;
	else
		a = convert_rational_to_double(p1);

	if (isdouble(p2))
		b = p2->u.d;
	else
		b = convert_rational_to_double(p2);

	push_double(a + b);

	restore();
}
Пример #3
0
void
negate_number(void)
{
	save();
	p1 = pop();
	if (iszero(p1)) {
		push(p1);
		restore();
		return;
	}
	switch (p1->k) {
	case NUM:
		p2 = alloc();
		p2->k = NUM;
		p2->u.q.a = mcopy(p1->u.q.a);
		p2->u.q.b = mcopy(p1->u.q.b);
		MSIGN(p2->u.q.a) *= -1;
		push(p2);
		break;
	case DOUBLE:
		push_double(-p1->u.d);
		break;
	default:
		stop("bug caught in mp_negate_number");
		break;
	}
	restore();
}
Пример #4
0
void
arcsinh(void)
{
	double d;
	save();
	p1 = pop();
	if (car(p1) == symbol(SINH)) {
		push(cadr(p1));
		restore();
		return;
	}
	if (isdouble(p1)) {
		d = p1->u.d;
		d = log(d + sqrt(d * d + 1.0));
		push_double(d);
		restore();
		return;
	}
	if (iszero(p1)) {
		push(zero);
		restore();
		return;
	}
	push_symbol(ARCSINH);
	push(p1);
	list(2);
	restore();
}
Пример #5
0
void
divide_numbers(void)
{
	double a, b;

	if (isrational(stack[tos - 1]) && isrational(stack[tos - 2])) {
		qdiv();
		return;
	}

	save();

	p2 = pop();
	p1 = pop();

	if (iszero(p2))
		stop("divide by zero");

	if (isdouble(p1))
		a = p1->u.d;
	else
		a = convert_rational_to_double(p1);

	if (isdouble(p2))
		b = p2->u.d;
	else
		b = convert_rational_to_double(p2);

	push_double(a / b);

	restore();
}
Пример #6
0
void
invert_number(void)
{
	unsigned int *a, *b;

	save();

	p1 = pop();

	if (iszero(p1))
		stop("divide by zero");

	if (isdouble(p1)) {
		push_double(1 / p1->u.d);
		restore();
		return;
	}

	a = mcopy(p1->u.q.a);
	b = mcopy(p1->u.q.b);

	MSIGN(b) = MSIGN(a);
	MSIGN(a) = 1;

	p1 = alloc();

	p1->k = NUM;

	p1->u.q.a = b;
	p1->u.q.b = a;

	push(p1);

	restore();
}
Пример #7
0
static void
yyerf(void)
{
	double d;

	p1 = pop();

	if (isdouble(p1)) {
		d = 1.0 - erfc(p1->u.d);
		push_double(d);
		return;
	}

	if (isnegativeterm(p1)) {
		push_symbol(ERF);
		push(p1);
		negate();
		list(2);
		negate();
		return;
	}
	
	push_symbol(ERF);
	push(p1);
	list(2);
	return;
}
Пример #8
0
void
arctanh(void)
{
	double d;
	save();
	p1 = pop();
	if (car(p1) == symbol(TANH)) {
		push(cadr(p1));
		restore();
		return;
	}
	if (isdouble(p1)) {
		d = p1->u.d;
		if (d < -1.0 || d > 1.0)
			stop("arctanh function argument is not in the interval [-1,1]");
		d = log((1.0 + d) / (1.0 - d)) / 2.0;
		push_double(d);
		restore();
		return;
	}
	if (iszero(p1)) {
		push(zero);
		restore();
		return;
	}
	push_symbol(ARCTANH);
	push(p1);
	list(2);
	restore();
}
Пример #9
0
void
arccosh(void)
{
	double d;
	save();
	p1 = pop();
	if (car(p1) == symbol(COSH)) {
		push(cadr(p1));
		restore();
		return;
	}
	if (isdouble(p1)) {
		d = p1->u.d;
		if (d < 1.0)
			stop("arccosh function argument is less than 1.0");
		d = log(d + sqrt(d * d - 1.0));
		push_double(d);
		restore();
		return;
	}
	if (isplusone(p1)) {
		push(zero);
		restore();
		return;
	}
	push_symbol(ARCCOSH);
	push(p1);
	list(2);
	restore();
}
Пример #10
0
Status push_constant(const char *value, Stack **operands)
{
    double x = 0.0;

    if (strcasecmp(value, "e") == 0)
    {
        x = M_E;
    }
    else if (strcasecmp(value, "pi") == 0)
    {
        x = M_PI;
    }
    else if (strcasecmp(value, "tau") == 0)
    {
        x = M_PI * 2;
    }
    else
    {
        return ERROR_UNDEFINED_CONSTANT;
    }

    push_double(x, operands);

    return OK;
}
Пример #11
0
Status apply_operator(const Operator *operator, Stack **operands)
{
    if (!operator || !*operands)
    {
        return ERROR_SYNTAX;
    }

    if (operator->arity == OPERATOR_UNARY)
    {
        return apply_unary_operator(operator, operands);
    }

    double y = pop_double(operands);

    if (!*operands)
    {
        return ERROR_SYNTAX;
    }

    double x = pop_double(operands);
    Status status = OK;

    switch (operator->symbol)
    {
        case '^':
            x = pow(x, y);
            break;
        case '*':
            x = x * y;
            break;
        case '/':
            x = x / y;
            break;
        case '%':
            x = fmod(x, y);
            break;
        case '+':
            x = x + y;
            break;
        case '-':
            x = x - y;
            break;
        default:
            return ERROR_UNRECOGNIZED;
    }

    push_double(x, operands);

    return status;
}
Пример #12
0
Status apply_function(const char *function, Stack **operands)
{
    if (!*operands)
    {
        return ERROR_FUNCTION_ARGUMENTS;
    }

    double x = pop_double(operands);

    if (strcasecmp(function, "abs") == 0)
    {
        x = fabs(x);
    }
    else if (strcasecmp(function, "sqrt") == 0)
    {
        x = sqrt(x);
    }
    else if (strcasecmp(function, "ln") == 0)
    {
        x = log(x);
    }
    else if (strcasecmp(function, "lb") == 0)
    {
        x = log2(x);
    }
    else if (strcasecmp(function, "lg") == 0 || strcasecmp(function, "log") == 0)
    {
        x = log10(x);
    }
    else if (strcasecmp(function, "cos") == 0)
    {
        x = cos(x);
    }
    else if (strcasecmp(function, "sin") == 0)
    {
        x = sin(x);
    }
    else if (strcasecmp(function, "tan") == 0)
    {
        x = tan(x);
    }
    else
    {
        return ERROR_UNDEFINED_FUNCTION;
    }

    push_double(x, operands);

    return OK;
}
Пример #13
0
Status push_number(const char *value, Stack **operands)
{
    char *end_pointer = NULL;
    double x = strtod(value, &end_pointer);

    // If not all of the value is converted, the rest is invalid.
    if (value + strlen(value) != end_pointer)
    {
        return ERROR_SYNTAX;
    }

    push_double(x, operands);
    return OK;
}
Пример #14
0
void
get_xy(double t)
{
	eval_f(t);

	p1 = pop();

	if (istensor(p1)) {
		if (p1->u.tensor->nelem >= 2) {
			XT = p1->u.tensor->elem[0];
			YT = p1->u.tensor->elem[1];
		} else {
			XT = symbol(NIL);
			YT = symbol(NIL);
		}
		return;
	}

	push_double(t);
	XT = pop();
	YT = p1;
}
Пример #15
0
Status apply_unary_operator(const Operator *operator, Stack **operands)
{
    double x = pop_double(operands);

    switch (operator->symbol)
    {
        case '+':
            break;
        case '-':
            x = -x;
            break;
        case '!':
            x = tgamma(x + 1);
            break;
        default:
            return ERROR_UNRECOGNIZED;
    }

    push_double(x, operands);

    return OK;
}
Пример #16
0
void
yybessely(void)
{
	double d;
	int n;

	N = pop();
	X = pop();

	push(N);
	n = pop_integer();

	if (isdouble(X) && n != (int) 0x80000000) {
		d = yn(n, X->u.d);
		push_double(d);
		return;
	}
	
	if (isnegativeterm(N)) {
		push_integer(-1);
		push(N);
		power();
		push_symbol(BESSELY);
		push(X);
		push(N);
		negate();
		list(3);
		multiply();
		return;
	}

	push_symbol(BESSELY);
	push(X);
	push(N);
	list(3);
	return;
}
Пример #17
0
void
yysinh(void)
{
	double d;
	p1 = pop();
	if (car(p1) == symbol(ARCSINH)) {
		push(cadr(p1));
		return;
	}
	if (isdouble(p1)) {
		d = sinh(p1->u.d);
		if (fabs(d) < 1e-10)
			d = 0.0;
		push_double(d);
		return;
	}
	if (iszero(p1)) {
		push(zero);
		return;
	}
	push_symbol(SINH);
	push(p1);
	list(2);
}
Пример #18
0
void
yyfloor(void)
{
	double d;

	p1 = pop();

	if (!isnum(p1)) {
		push_symbol(FLOOR);
		push(p1);
		list(2);
		return;
	}

	if (isdouble(p1)) {
		d = floor(p1->u.d);
		push_double(d);
		return;
	}

	if (isinteger(p1)) {
		push(p1);
		return;
	}

	p3 = alloc();
	p3->k = NUM;
	p3->u.q.a = mdiv(p1->u.q.a, p1->u.q.b);
	p3->u.q.b = mint(1);
	push(p3);

	if (isnegativenumber(p1)) {
		push_integer(-1);
		add();
	}
}
Пример #19
0
void
eval_f(double t)
{
	// These must be volatile or it crashes. (Compiler error?)
	// Read it backwards, save_tos is a volatile int, etc.

	int volatile save_tos;
	U ** volatile save_frame;

	save();
	save_tos = tos;
	save_frame = frame;

	draw_flag++;

	if (setjmp(draw_stop_return)) {
		tos = save_tos;
		push(symbol(NIL));
		frame = save_frame;
		restore();
		draw_flag--;
		return;
	}

	push_double(t);
	p1 = pop();
	set_binding(T, p1);

	push(F);
	eval();
	yyfloat();
	eval();

	restore();
	draw_flag--;
}
Пример #20
0
void
arctan(void)
{
	double d;

	save();

	p1 = pop();

	if (car(p1) == symbol(TAN)) {
		push(cadr(p1));
		restore();
		return;
	}

	if (isdouble(p1)) {
		errno = 0;
		d = atan(p1->u.d);
		if (errno)
			stop("arctan function error");
		push_double(d);
		restore();
		return;
	}

	if (iszero(p1)) {
		push(zero);
		restore();
		return;
	}

	if (isnegative(p1)) {
		push(p1);
		negate();
		arctan();
		negate();
		restore();
		return;
	}

	// arctan(sin(a) / cos(a)) ?

	if (find(p1, symbol(SIN)) && find(p1, symbol(COS))) {
		push(p1);
		numerator();
		p2 = pop();
		push(p1);
		denominator();
		p3 = pop();
		if (car(p2) == symbol(SIN) && car(p3) == symbol(COS) && equal(cadr(p2), cadr(p3))) {
			push(cadr(p2));
			restore();
			return;
		}
	}

	// arctan(1/sqrt(3)) -> pi/6

	if (car(p1) == symbol(POWER) && equaln(cadr(p1), 3) && equalq(caddr(p1), -1, 2)) {
		push_rational(1, 6);
		push(symbol(PI));
		multiply();
		restore();
		return;
	}

	// arctan(1) -> pi/4

	if (equaln(p1, 1)) {
		push_rational(1, 4);
		push(symbol(PI));
		multiply();
		restore();
		return;
	}

	// arctan(sqrt(3)) -> pi/3

	if (car(p1) == symbol(POWER) && equaln(cadr(p1), 3) && equalq(caddr(p1), 1, 2)) {
		push_rational(1, 3);
		push(symbol(PI));
		multiply();
		restore();
		return;
	}

	push_symbol(ARCTAN);
	push(p1);
	list(2);

	restore();
}
void
yypower(void)
{
	int n;

	p2 = pop();
	p1 = pop();

	// both base and exponent are rational numbers?

	if (isrational(p1) && isrational(p2)) {
		push(p1);
		push(p2);
		qpow();
		return;
	}

	// both base and exponent are either rational or double?

	if (isnum(p1) && isnum(p2)) {
		push(p1);
		push(p2);
		dpow();
		return;
	}

	if (istensor(p1)) {
		power_tensor();
		return;
	}

	if (p1 == symbol(E) && car(p2) == symbol(LOG)) {
		push(cadr(p2));
		return;
	}

	if (p1 == symbol(E) && isdouble(p2)) {
		push_double(exp(p2->u.d));
		return;
	}

	//	1 ^ a		->	1

	//	a ^ 0		->	1

	if (equal(p1, one) || iszero(p2)) {
		push(one);
		return;
	}

	//	a ^ 1		->	a

	if (equal(p2, one)) {
		push(p1);
		return;
	}

	//	(a * b) ^ c	->	(a ^ c) * (b ^ c)

	if (car(p1) == symbol(MULTIPLY)) {
		p1 = cdr(p1);
		push(car(p1));
		push(p2);
		power();
		p1 = cdr(p1);
		while (iscons(p1)) {
			push(car(p1));
			push(p2);
			power();
			multiply();
			p1 = cdr(p1);
		}
		return;
	}

	//	(a ^ b) ^ c	->	a ^ (b * c)

	if (car(p1) == symbol(POWER)) {
		push(cadr(p1));
		push(caddr(p1));
		push(p2);
		multiply();
		power();
		return;
	}

	//	(a + b) ^ n	->	(a + b) * (a + b) ...

	if (expanding && isadd(p1) && isnum(p2)) {
		push(p2);
		n = pop_integer();
        // this && n != 0x80000000 added by DDC
        // as it's not always the case that 0x80000000
        // is negative
		if (n > 1 && n != 0x80000000) {
			power_sum(n);
			return;
		}
	}

	//	sin(x) ^ 2n -> (1 - cos(x) ^ 2) ^ n

	if (trigmode == 1 && car(p1) == symbol(SIN) && iseveninteger(p2)) {
		push_integer(1);
		push(cadr(p1));
		cosine();
		push_integer(2);
		power();
		subtract();
		push(p2);
		push_rational(1, 2);
		multiply();
		power();
		return;
	}

	//	cos(x) ^ 2n -> (1 - sin(x) ^ 2) ^ n

	if (trigmode == 2 && car(p1) == symbol(COS) && iseveninteger(p2)) {
		push_integer(1);
		push(cadr(p1));
		sine();
		push_integer(2);
		power();
		subtract();
		push(p2);
		push_rational(1, 2);
		multiply();
		power();
		return;
	}

	// complex number? (just number, not expression)

	if (iscomplexnumber(p1)) {

		// integer power?

		// n will be negative here, positive n already handled

		if (isinteger(p2)) {

			//               /        \  n
			//         -n   |  a - ib  |
			// (a + ib)   = | -------- |
			//              |   2   2  |
			//               \ a + b  /

			push(p1);
			conjugate();
			p3 = pop();
			push(p3);
			push(p3);
			push(p1);
			multiply();
			divide();
			push(p2);
			negate();
			power();
			return;
		}

		// noninteger or floating power?

		if (isnum(p2)) {

#if 1			// use polar form
			push(p1);
			mag();
			push(p2);
			power();
			push_integer(-1);
			push(p1);
			arg();
			push(p2);
			multiply();
			push(symbol(PI));
			divide();
			power();
			multiply();

#else			// use exponential form
			push(p1);
			mag();
			push(p2);
			power();
			push(symbol(E));
			push(p1);
			arg();
			push(p2);
			multiply();
			push(imaginaryunit);
			multiply();
			power();
			multiply();
#endif
			return;
		}
	}

	if (simplify_polar())
		return;

	push_symbol(POWER);
	push(p1);
	push(p2);
	list(3);
}
Пример #22
0
void
eval_nroots(void)
{
	volatile int h, i, k, n;

	push(cadr(p1));
	eval();

	push(caddr(p1));
	eval();
	p2 = pop();
	if (p2 == symbol(NIL))
		guess();
	else
		push(p2);

	p2 = pop();
	p1 = pop();

	if (!ispoly(p1, p2))
		stop("nroots: polynomial?");

	// mark the stack

	h = tos;

	// get the coefficients

	push(p1);
	push(p2);
	n = coeff();
	if (n > YMAX)
		stop("nroots: degree?");

	// convert the coefficients to real and imaginary doubles

	for (i = 0; i < n; i++) {
		push(stack[h + i]);
		real();
		yyfloat();
		eval();
		p1 = pop();
		push(stack[h + i]);
		imag();
		yyfloat();
		eval();
		p2 = pop();
		if (!isdouble(p1) || !isdouble(p2))
			stop("nroots: coefficients?");
		c[i].r = p1->u.d;
		c[i].i = p2->u.d;
	}

	// pop the coefficients

	tos = h;

	// n is the number of coefficients, n = deg(p) + 1

	monic(n);

	for (k = n; k > 1; k--) {
		findroot(k);
		if (fabs(a.r) < DELTA)
			a.r = 0.0;
		if (fabs(a.i) < DELTA)
			a.i = 0.0;
		push_double(a.r);
		push_double(a.i);
		push(imaginaryunit);
		multiply();
		add();
		divpoly(k);
	}

	// now make n equal to the number of roots

	n = tos - h;

	if (n > 1) {
		sort_stack(n);
		p1 = alloc_tensor(n);
		p1->u.tensor->ndim = 1;
		p1->u.tensor->dim[0] = n;
		for (i = 0; i < n; i++)
			p1->u.tensor->elem[i] = stack[h + i];
		tos = h;
		push(p1);
	}
}
Пример #23
0
void
bignum_scan_float(char *s)
{
	//push_double(atof(s));
	push_double(mystrtod((char*)s, NULL));
}
Пример #24
0
void
yybesselj(void)
{
	double d;
	int n;

	N = pop();
	X = pop();

	push(N);
	n = pop_integer();

	// numerical result

	if (isdouble(X) && n != (int) 0x80000000) {
		//d = jn(n, X->u.d);
		push_double(d);
		return;
	}

	// bessej(0,0) = 1

	if (iszero(X) && iszero(N)) {
		push_integer(1);
		return;
	}

	// besselj(0,n) = 0

	if (iszero(X) && n != (int) 0x80000000) {
		push_integer(0);
		return;
	}

	// half arguments

	if (N->k == NUM && MEQUAL(N->u.q.b, 2)) {

		// n = 1/2

		if (MEQUAL(N->u.q.a, 1)) {
			push_integer(2);
			push_symbol(PI);
			divide();
			push(X);
			divide();
			push_rational(1, 2);
			power();
			push(X);
			sine();
			multiply();
			return;
		}

		// n = -1/2

		if (MEQUAL(N->u.q.a, -1)) {
			push_integer(2);
			push_symbol(PI);
			divide();
			push(X);
			divide();
			push_rational(1, 2);
			power();
			push(X);
			cosine();
			multiply();
			return;
		}

		// besselj(x,n) = (2/x) (n-sgn(n)) besselj(x,n-sgn(n)) - besselj(x,n-2*sgn(n))

		push_integer(MSIGN(N->u.q.a));
		SGN = pop();

		push_integer(2);
		push(X);
		divide();
		push(N);
		push(SGN);
		subtract();
		multiply();
		push(X);
		push(N);
		push(SGN);
		subtract();
		besselj();
		multiply();
		push(X);
		push(N);
		push_integer(2);
		push(SGN);
		multiply();
		subtract();
		besselj();
		subtract();

		return;
	}


	push(symbol(BESSELJ));
	push(X);
	push(N);
	list(3);
}
Пример #25
0
void
cosine_of_angle(void)
{
	int n;
	double d;

	if (car(p1) == symbol(ARCCOS)) {
		push(cadr(p1));
		return;
	}

	if (isdouble(p1)) {
		d = cos(p1->u.d);
		if (fabs(d) < 1e-10)
			d = 0.0;
		push_double(d);
		return;
	}

	// cosine function is symmetric, cos(-x) = cos(x)

	if (isnegative(p1)) {
		push(p1);
		negate();
		p1 = pop();
	}

	// cos(arctan(x)) = 1 / sqrt(1 + x^2)

	// see p. 173 of the CRC Handbook of Mathematical Sciences

	if (car(p1) == symbol(ARCTAN)) {
		push_integer(1);
		push(cadr(p1));
		push_integer(2);
		power();
		add();
		push_rational(-1, 2);
		power();
		return;
	}

	// multiply by 180/pi

	push(p1);
	push_integer(180);
	multiply();
	push_symbol(PI);
	divide();

	n = pop_integer();

	if (n < 0) {
		push(symbol(COS));
		push(p1);
		list(2);
		return;
	}

	switch (n % 360) {
	case 90:
	case 270:
		push_integer(0);
		break;
	case 60:
	case 300:
		push_rational(1, 2);
		break;
	case 120:
	case 240:
		push_rational(-1, 2);
		break;
	case 45:
	case 315:
		push_rational(1, 2);
		push_integer(2);
		push_rational(1, 2);
		power();
		multiply();
		break;
	case 135:
	case 225:
		push_rational(-1, 2);
		push_integer(2);
		push_rational(1, 2);
		power();
		multiply();
		break;
	case 30:
	case 330:
		push_rational(1, 2);
		push_integer(3);
		push_rational(1, 2);
		power();
		multiply();
		break;
	case 150:
	case 210:
		push_rational(-1, 2);
		push_integer(3);
		push_rational(1, 2);
		power();
		multiply();
		break;
	case 0:
		push_integer(1);
		break;
	case 180:
		push_integer(-1);
		break;
	default:
		push(symbol(COS));
		push(p1);
		list(2);
		break;
	}
}